1 // Copyright (c) 2015-2016 The btcsuite developers
2 // Use of this source code is governed by an ISC
3 // license that can be found in the LICENSE file.
5 // Parts of this interface were inspired heavily by the excellent boltdb project
6 // at https://github.com/boltdb/bolt by Ben B. Johnson.
11 "github.com/btcsuite/btcd/chaincfg/chainhash"
12 "github.com/btcsuite/btcutil"
15 // Cursor represents a cursor over key/value pairs and nested buckets of a
18 // Note that open cursors are not tracked on bucket changes and any
19 // modifications to the bucket, with the exception of Cursor.Delete, invalidates
20 // the cursor. After invalidation, the cursor must be repositioned, or the keys
21 // and values returned may be unpredictable.
22 type Cursor interface {
23 // Bucket returns the bucket the cursor was created for.
26 // Delete removes the current key/value pair the cursor is at without
27 // invalidating the cursor.
29 // The interface contract guarantees at least the following errors will
30 // be returned (other implementation-specific errors are possible):
31 // - ErrIncompatibleValue if attempted when the cursor points to a
33 // - ErrTxNotWritable if attempted against a read-only transaction
34 // - ErrTxClosed if the transaction has already been closed
37 // First positions the cursor at the first key/value pair and returns
38 // whether or not the pair exists.
41 // Last positions the cursor at the last key/value pair and returns
42 // whether or not the pair exists.
45 // Next moves the cursor one key/value pair forward and returns whether
46 // or not the pair exists.
49 // Prev moves the cursor one key/value pair backward and returns whether
50 // or not the pair exists.
53 // Seek positions the cursor at the first key/value pair that is greater
54 // than or equal to the passed seek key. Returns whether or not the
56 Seek(seek []byte) bool
58 // Key returns the current key the cursor is pointing to.
61 // Value returns the current value the cursor is pointing to. This will
62 // be nil for nested buckets.
66 // Bucket represents a collection of key/value pairs.
67 type Bucket interface {
68 // Bucket retrieves a nested bucket with the given key. Returns nil if
69 // the bucket does not exist.
70 Bucket(key []byte) Bucket
72 // CreateBucket creates and returns a new nested bucket with the given
75 // The interface contract guarantees at least the following errors will
76 // be returned (other implementation-specific errors are possible):
77 // - ErrBucketExists if the bucket already exists
78 // - ErrBucketNameRequired if the key is empty
79 // - ErrIncompatibleValue if the key is otherwise invalid for the
80 // particular implementation
81 // - ErrTxNotWritable if attempted against a read-only transaction
82 // - ErrTxClosed if the transaction has already been closed
83 CreateBucket(key []byte) (Bucket, error)
85 // CreateBucketIfNotExists creates and returns a new nested bucket with
86 // the given key if it does not already exist.
88 // The interface contract guarantees at least the following errors will
89 // be returned (other implementation-specific errors are possible):
90 // - ErrBucketNameRequired if the key is empty
91 // - ErrIncompatibleValue if the key is otherwise invalid for the
92 // particular implementation
93 // - ErrTxNotWritable if attempted against a read-only transaction
94 // - ErrTxClosed if the transaction has already been closed
95 CreateBucketIfNotExists(key []byte) (Bucket, error)
97 // DeleteBucket removes a nested bucket with the given key. This also
98 // includes removing all nested buckets and keys under the bucket being
101 // The interface contract guarantees at least the following errors will
102 // be returned (other implementation-specific errors are possible):
103 // - ErrBucketNotFound if the specified bucket does not exist
104 // - ErrTxNotWritable if attempted against a read-only transaction
105 // - ErrTxClosed if the transaction has already been closed
106 DeleteBucket(key []byte) error
108 // ForEach invokes the passed function with every key/value pair in the
109 // bucket. This does not include nested buckets or the key/value pairs
110 // within those nested buckets.
112 // WARNING: It is not safe to mutate data while iterating with this
113 // method. Doing so may cause the underlying cursor to be invalidated
114 // and return unexpected keys and/or values.
116 // The interface contract guarantees at least the following errors will
117 // be returned (other implementation-specific errors are possible):
118 // - ErrTxClosed if the transaction has already been closed
120 // NOTE: The slices returned by this function are only valid during a
121 // transaction. Attempting to access them after a transaction has ended
122 // results in undefined behavior. Additionally, the slices must NOT
123 // be modified by the caller. These constraints prevent additional data
124 // copies and allows support for memory-mapped database implementations.
125 ForEach(func(k, v []byte) error) error
127 // ForEachBucket invokes the passed function with the key of every
128 // nested bucket in the current bucket. This does not include any
129 // nested buckets within those nested buckets.
131 // WARNING: It is not safe to mutate data while iterating with this
132 // method. Doing so may cause the underlying cursor to be invalidated
133 // and return unexpected keys and/or values.
135 // The interface contract guarantees at least the following errors will
136 // be returned (other implementation-specific errors are possible):
137 // - ErrTxClosed if the transaction has already been closed
139 // NOTE: The keys returned by this function are only valid during a
140 // transaction. Attempting to access them after a transaction has ended
141 // results in undefined behavior. This constraint prevents additional
142 // data copies and allows support for memory-mapped database
144 ForEachBucket(func(k []byte) error) error
146 // Cursor returns a new cursor, allowing for iteration over the bucket's
147 // key/value pairs and nested buckets in forward or backward order.
149 // You must seek to a position using the First, Last, or Seek functions
150 // before calling the Next, Prev, Key, or Value functions. Failure to
151 // do so will result in the same return values as an exhausted cursor,
152 // which is false for the Prev and Next functions and nil for Key and
156 // Writable returns whether or not the bucket is writable.
159 // Put saves the specified key/value pair to the bucket. Keys that do
160 // not already exist are added and keys that already exist are
163 // The interface contract guarantees at least the following errors will
164 // be returned (other implementation-specific errors are possible):
165 // - ErrKeyRequired if the key is empty
166 // - ErrIncompatibleValue if the key is the same as an existing bucket
167 // - ErrTxNotWritable if attempted against a read-only transaction
168 // - ErrTxClosed if the transaction has already been closed
170 // NOTE: The slices passed to this function must NOT be modified by the
171 // caller. This constraint prevents the requirement for additional data
172 // copies and allows support for memory-mapped database implementations.
173 Put(key, value []byte) error
175 // Get returns the value for the given key. Returns nil if the key does
176 // not exist in this bucket. An empty slice is returned for keys that
177 // exist but have no value assigned.
179 // NOTE: The value returned by this function is only valid during a
180 // transaction. Attempting to access it after a transaction has ended
181 // results in undefined behavior. Additionally, the value must NOT
182 // be modified by the caller. These constraints prevent additional data
183 // copies and allows support for memory-mapped database implementations.
184 Get(key []byte) []byte
186 // Delete removes the specified key from the bucket. Deleting a key
187 // that does not exist does not return an error.
189 // The interface contract guarantees at least the following errors will
190 // be returned (other implementation-specific errors are possible):
191 // - ErrKeyRequired if the key is empty
192 // - ErrIncompatibleValue if the key is the same as an existing bucket
193 // - ErrTxNotWritable if attempted against a read-only transaction
194 // - ErrTxClosed if the transaction has already been closed
195 Delete(key []byte) error
198 // BlockRegion specifies a particular region of a block identified by the
199 // specified hash, given an offset and length.
200 type BlockRegion struct {
206 // Tx represents a database transaction. It can either by read-only or
207 // read-write. The transaction provides a metadata bucket against which all
208 // read and writes occur.
210 // As would be expected with a transaction, no changes will be saved to the
211 // database until it has been committed. The transaction will only provide a
212 // view of the database at the time it was created. Transactions should not be
213 // long running operations.
215 // Metadata returns the top-most bucket for all metadata storage.
218 // StoreBlock stores the provided block into the database. There are no
219 // checks to ensure the block connects to a previous block, contains
220 // double spends, or any additional functionality such as transaction
221 // indexing. It simply stores the block in the database.
223 // The interface contract guarantees at least the following errors will
224 // be returned (other implementation-specific errors are possible):
225 // - ErrBlockExists when the block hash already exists
226 // - ErrTxNotWritable if attempted against a read-only transaction
227 // - ErrTxClosed if the transaction has already been closed
229 // Other errors are possible depending on the implementation.
230 StoreBlock(block *btcutil.Block) error
232 // HasBlock returns whether or not a block with the given hash exists
235 // The interface contract guarantees at least the following errors will
236 // be returned (other implementation-specific errors are possible):
237 // - ErrTxClosed if the transaction has already been closed
239 // Other errors are possible depending on the implementation.
240 HasBlock(hash *chainhash.Hash) (bool, error)
242 // HasBlocks returns whether or not the blocks with the provided hashes
243 // exist in the database.
245 // The interface contract guarantees at least the following errors will
246 // be returned (other implementation-specific errors are possible):
247 // - ErrTxClosed if the transaction has already been closed
249 // Other errors are possible depending on the implementation.
250 HasBlocks(hashes []chainhash.Hash) ([]bool, error)
252 // FetchBlockHeader returns the raw serialized bytes for the block
253 // header identified by the given hash. The raw bytes are in the format
254 // returned by Serialize on a wire.BlockHeader.
256 // It is highly recommended to use this function (or FetchBlockHeaders)
257 // to obtain block headers over the FetchBlockRegion(s) functions since
258 // it provides the backend drivers the freedom to perform very specific
259 // optimizations which can result in significant speed advantages when
260 // working with headers.
262 // The interface contract guarantees at least the following errors will
263 // be returned (other implementation-specific errors are possible):
264 // - ErrBlockNotFound if the requested block hash does not exist
265 // - ErrTxClosed if the transaction has already been closed
266 // - ErrCorruption if the database has somehow become corrupted
268 // NOTE: The data returned by this function is only valid during a
269 // database transaction. Attempting to access it after a transaction
270 // has ended results in undefined behavior. This constraint prevents
271 // additional data copies and allows support for memory-mapped database
273 FetchBlockHeader(hash *chainhash.Hash) ([]byte, error)
275 // FetchBlockHeaders returns the raw serialized bytes for the block
276 // headers identified by the given hashes. The raw bytes are in the
277 // format returned by Serialize on a wire.BlockHeader.
279 // It is highly recommended to use this function (or FetchBlockHeader)
280 // to obtain block headers over the FetchBlockRegion(s) functions since
281 // it provides the backend drivers the freedom to perform very specific
282 // optimizations which can result in significant speed advantages when
283 // working with headers.
285 // Furthermore, depending on the specific implementation, this function
286 // can be more efficient for bulk loading multiple block headers than
287 // loading them one-by-one with FetchBlockHeader.
289 // The interface contract guarantees at least the following errors will
290 // be returned (other implementation-specific errors are possible):
291 // - ErrBlockNotFound if any of the request block hashes do not exist
292 // - ErrTxClosed if the transaction has already been closed
293 // - ErrCorruption if the database has somehow become corrupted
295 // NOTE: The data returned by this function is only valid during a
296 // database transaction. Attempting to access it after a transaction
297 // has ended results in undefined behavior. This constraint prevents
298 // additional data copies and allows support for memory-mapped database
300 FetchBlockHeaders(hashes []chainhash.Hash) ([][]byte, error)
302 // FetchBlock returns the raw serialized bytes for the block identified
303 // by the given hash. The raw bytes are in the format returned by
304 // Serialize on a wire.MsgBlock.
306 // The interface contract guarantees at least the following errors will
307 // be returned (other implementation-specific errors are possible):
308 // - ErrBlockNotFound if the requested block hash does not exist
309 // - ErrTxClosed if the transaction has already been closed
310 // - ErrCorruption if the database has somehow become corrupted
312 // NOTE: The data returned by this function is only valid during a
313 // database transaction. Attempting to access it after a transaction
314 // has ended results in undefined behavior. This constraint prevents
315 // additional data copies and allows support for memory-mapped database
317 FetchBlock(hash *chainhash.Hash) ([]byte, error)
319 // FetchBlocks returns the raw serialized bytes for the blocks
320 // identified by the given hashes. The raw bytes are in the format
321 // returned by Serialize on a wire.MsgBlock.
323 // The interface contract guarantees at least the following errors will
324 // be returned (other implementation-specific errors are possible):
325 // - ErrBlockNotFound if the any of the requested block hashes do not
327 // - ErrTxClosed if the transaction has already been closed
328 // - ErrCorruption if the database has somehow become corrupted
330 // NOTE: The data returned by this function is only valid during a
331 // database transaction. Attempting to access it after a transaction
332 // has ended results in undefined behavior. This constraint prevents
333 // additional data copies and allows support for memory-mapped database
335 FetchBlocks(hashes []chainhash.Hash) ([][]byte, error)
337 // FetchBlockRegion returns the raw serialized bytes for the given
340 // For example, it is possible to directly extract Bitcoin transactions
341 // and/or scripts from a block with this function. Depending on the
342 // backend implementation, this can provide significant savings by
343 // avoiding the need to load entire blocks.
345 // The raw bytes are in the format returned by Serialize on a
346 // wire.MsgBlock and the Offset field in the provided BlockRegion is
347 // zero-based and relative to the start of the block (byte 0).
349 // The interface contract guarantees at least the following errors will
350 // be returned (other implementation-specific errors are possible):
351 // - ErrBlockNotFound if the requested block hash does not exist
352 // - ErrBlockRegionInvalid if the region exceeds the bounds of the
354 // - ErrTxClosed if the transaction has already been closed
355 // - ErrCorruption if the database has somehow become corrupted
357 // NOTE: The data returned by this function is only valid during a
358 // database transaction. Attempting to access it after a transaction
359 // has ended results in undefined behavior. This constraint prevents
360 // additional data copies and allows support for memory-mapped database
362 FetchBlockRegion(region *BlockRegion) ([]byte, error)
364 // FetchBlockRegions returns the raw serialized bytes for the given
367 // For example, it is possible to directly extract Bitcoin transactions
368 // and/or scripts from various blocks with this function. Depending on
369 // the backend implementation, this can provide significant savings by
370 // avoiding the need to load entire blocks.
372 // The raw bytes are in the format returned by Serialize on a
373 // wire.MsgBlock and the Offset fields in the provided BlockRegions are
374 // zero-based and relative to the start of the block (byte 0).
376 // The interface contract guarantees at least the following errors will
377 // be returned (other implementation-specific errors are possible):
378 // - ErrBlockNotFound if any of the requested block hashed do not
380 // - ErrBlockRegionInvalid if one or more region exceed the bounds of
381 // the associated block
382 // - ErrTxClosed if the transaction has already been closed
383 // - ErrCorruption if the database has somehow become corrupted
385 // NOTE: The data returned by this function is only valid during a
386 // database transaction. Attempting to access it after a transaction
387 // has ended results in undefined behavior. This constraint prevents
388 // additional data copies and allows support for memory-mapped database
390 FetchBlockRegions(regions []BlockRegion) ([][]byte, error)
392 // ******************************************************************
393 // Methods related to both atomic metadata storage and block storage.
394 // ******************************************************************
396 // Commit commits all changes that have been made to the metadata or
397 // block storage. Depending on the backend implementation this could be
398 // to a cache that is periodically synced to persistent storage or
399 // directly to persistent storage. In any case, all transactions which
400 // are started after the commit finishes will include all changes made
401 // by this transaction. Calling this function on a managed transaction
402 // will result in a panic.
405 // Rollback undoes all changes that have been made to the metadata or
406 // block storage. Calling this function on a managed transaction will
407 // result in a panic.
411 // DB provides a generic interface that is used to store bitcoin blocks and
412 // related metadata. This interface is intended to be agnostic to the actual
413 // mechanism used for backend data storage. The RegisterDriver function can be
414 // used to add a new backend data storage method.
416 // This interface is divided into two distinct categories of functionality.
418 // The first category is atomic metadata storage with bucket support. This is
419 // accomplished through the use of database transactions.
421 // The second category is generic block storage. This functionality is
422 // intentionally separate because the mechanism used for block storage may or
423 // may not be the same mechanism used for metadata storage. For example, it is
424 // often more efficient to store the block data as flat files while the metadata
425 // is kept in a database. However, this interface aims to be generic enough to
426 // support blocks in the database too, if needed by a particular backend.
428 // Type returns the database driver type the current database instance
432 // Begin starts a transaction which is either read-only or read-write
433 // depending on the specified flag. Multiple read-only transactions
434 // can be started simultaneously while only a single read-write
435 // transaction can be started at a time. The call will block when
436 // starting a read-write transaction when one is already open.
438 // NOTE: The transaction must be closed by calling Rollback or Commit on
439 // it when it is no longer needed. Failure to do so can result in
440 // unclaimed memory and/or inablity to close the database due to locks
441 // depending on the specific database implementation.
442 Begin(writable bool) (Tx, error)
444 // View invokes the passed function in the context of a managed
445 // read-only transaction. Any errors returned from the user-supplied
446 // function are returned from this function.
448 // Calling Rollback or Commit on the transaction passed to the
449 // user-supplied function will result in a panic.
450 View(fn func(tx Tx) error) error
452 // Update invokes the passed function in the context of a managed
453 // read-write transaction. Any errors returned from the user-supplied
454 // function will cause the transaction to be rolled back and are
455 // returned from this function. Otherwise, the transaction is committed
456 // when the user-supplied function returns a nil error.
458 // Calling Rollback or Commit on the transaction passed to the
459 // user-supplied function will result in a panic.
460 Update(fn func(tx Tx) error) error
462 // Close cleanly shuts down the database and syncs all data. It will
463 // block until all database transactions have been finalized (rolled
464 // back or committed).