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.
4
5// Parts of this interface were inspired heavily by the excellent boltdb project
6// at https://github.com/boltdb/bolt by Ben B. Johnson.
7
8package database
9
10import (
11	"github.com/btcsuite/btcd/chaincfg/chainhash"
12	"github.com/btcsuite/btcutil"
13)
14
15// Cursor represents a cursor over key/value pairs and nested buckets of a
16// bucket.
17//
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.
22type Cursor interface {
23	// Bucket returns the bucket the cursor was created for.
24	Bucket() Bucket
25
26	// Delete removes the current key/value pair the cursor is at without
27	// invalidating the cursor.
28	//
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
32	//     nested bucket
33	//   - ErrTxNotWritable if attempted against a read-only transaction
34	//   - ErrTxClosed if the transaction has already been closed
35	Delete() error
36
37	// First positions the cursor at the first key/value pair and returns
38	// whether or not the pair exists.
39	First() bool
40
41	// Last positions the cursor at the last key/value pair and returns
42	// whether or not the pair exists.
43	Last() bool
44
45	// Next moves the cursor one key/value pair forward and returns whether
46	// or not the pair exists.
47	Next() bool
48
49	// Prev moves the cursor one key/value pair backward and returns whether
50	// or not the pair exists.
51	Prev() bool
52
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
55	// pair exists.
56	Seek(seek []byte) bool
57
58	// Key returns the current key the cursor is pointing to.
59	Key() []byte
60
61	// Value returns the current value the cursor is pointing to.  This will
62	// be nil for nested buckets.
63	Value() []byte
64}
65
66// Bucket represents a collection of key/value pairs.
67type 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
71
72	// CreateBucket creates and returns a new nested bucket with the given
73	// key.
74	//
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)
84
85	// CreateBucketIfNotExists creates and returns a new nested bucket with
86	// the given key if it does not already exist.
87	//
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)
96
97	// DeleteBucket removes a nested bucket with the given key.  This also
98	// includes removing all nested buckets and keys under the bucket being
99	// deleted.
100	//
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
107
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.
111	//
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.
115	//
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
119	//
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
126
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.
130	//
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.
134	//
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
138	//
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
143	// implementations.
144	ForEachBucket(func(k []byte) error) error
145
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.
148	//
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
153	// Value functions.
154	Cursor() Cursor
155
156	// Writable returns whether or not the bucket is writable.
157	Writable() bool
158
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
161	// overwritten.
162	//
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
169	//
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
174
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.
178	//
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
185
186	// Delete removes the specified key from the bucket.  Deleting a key
187	// that does not exist does not return an error.
188	//
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
196}
197
198// BlockRegion specifies a particular region of a block identified by the
199// specified hash, given an offset and length.
200type BlockRegion struct {
201	Hash   *chainhash.Hash
202	Offset uint32
203	Len    uint32
204}
205
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.
209//
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.
214type Tx interface {
215	// Metadata returns the top-most bucket for all metadata storage.
216	Metadata() Bucket
217
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.
222	//
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
228	//
229	// Other errors are possible depending on the implementation.
230	StoreBlock(block *btcutil.Block) error
231
232	// HasBlock returns whether or not a block with the given hash exists
233	// in the database.
234	//
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
238	//
239	// Other errors are possible depending on the implementation.
240	HasBlock(hash *chainhash.Hash) (bool, error)
241
242	// HasBlocks returns whether or not the blocks with the provided hashes
243	// exist in the database.
244	//
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
248	//
249	// Other errors are possible depending on the implementation.
250	HasBlocks(hashes []chainhash.Hash) ([]bool, error)
251
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.
255	//
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.
261	//
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
267	//
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
272	// implementations.
273	FetchBlockHeader(hash *chainhash.Hash) ([]byte, error)
274
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.
278	//
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.
284	//
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.
288	//
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
294	//
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
299	// implementations.
300	FetchBlockHeaders(hashes []chainhash.Hash) ([][]byte, error)
301
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.
305	//
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
311	//
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
316	// implementations.
317	FetchBlock(hash *chainhash.Hash) ([]byte, error)
318
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.
322	//
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
326	//     exist
327	//   - ErrTxClosed if the transaction has already been closed
328	//   - ErrCorruption if the database has somehow become corrupted
329	//
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
334	// implementations.
335	FetchBlocks(hashes []chainhash.Hash) ([][]byte, error)
336
337	// FetchBlockRegion returns the raw serialized bytes for the given
338	// block region.
339	//
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.
344	//
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).
348	//
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
353	//     associated block
354	//   - ErrTxClosed if the transaction has already been closed
355	//   - ErrCorruption if the database has somehow become corrupted
356	//
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
361	// implementations.
362	FetchBlockRegion(region *BlockRegion) ([]byte, error)
363
364	// FetchBlockRegions returns the raw serialized bytes for the given
365	// block regions.
366	//
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.
371	//
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).
375	//
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
379	//     exist
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
384	//
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
389	// implementations.
390	FetchBlockRegions(regions []BlockRegion) ([][]byte, error)
391
392	// ******************************************************************
393	// Methods related to both atomic metadata storage and block storage.
394	// ******************************************************************
395
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.
403	Commit() error
404
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.
408	Rollback() error
409}
410
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.
415//
416// This interface is divided into two distinct categories of functionality.
417//
418// The first category is atomic metadata storage with bucket support.  This is
419// accomplished through the use of database transactions.
420//
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.
427type DB interface {
428	// Type returns the database driver type the current database instance
429	// was created with.
430	Type() string
431
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.
437	//
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)
443
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.
447	//
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
451
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.
457	//
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
461
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).
465	Close() error
466}
467