Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

channeldb/kvdb: introduce new KV-store database abstraction #3833

Merged
merged 14 commits into from
Mar 19, 2020

Conversation

Roasbeef
Copy link
Member

@Roasbeef Roasbeef commented Dec 13, 2019

In this PR, we create a new package kvdb, which is meant to serve as the basis for any future database abstractions within lnd. Rather than directly use the walletdb package (which we base off of), we instead use a series of type-aliases to re-type the fundamental types/interfaces of the walletdb package. This lets us type kvdb.RwTx instead of walletdb.ReadWriteTransaction everywhere. Additionally, our usage of type-aliases is also intended to create an easy pathway in the future wherein we can gradually re-defined or re-implement these types to wean off of the walletdb package.

Cross-Over Considerations

One thing that we'll need to reconcile is that the CreateTopLevelBucket method for walletdb will return an error if the bucket doesn't exist, rather than creating the bucket just as CreateBucketIfNotExists for bbolt does. We can either make a small wrapper around the old interface to fix this, or just modify walletdb itself.

One other question is if we should go back and modify all the legacy migrations to use this new interface or not. Once new backends are added, there'll also come a time where we need to persist additional state to ensure that users can't arbitrarily move between backends (assuming they're replicated, a manual port would be needed).

What's Missing?

This PR is meant to just be a PoC (hence its marking as a draft PR) to demonstrate how we can easily introduce a new KV-like interface without limiting the future possibilities of a split database, or more high-level object methods (which would allow SQL based backends more flexibility w.r.t table structure).

Other things this PR needs to properly compile:

  • Finishing porting over all the main channeldb types to use the new kvdb package types.

  • Port over all the straggling instances of database usage outside the channeldb package

  • Figure out how we want to handle database upgrades (a two-level version maybe?), and the upgrade path to replicated databases.

@Roasbeef Roasbeef added database Related to the database/storage of LND golang/build system Related to the go language and compiler incomplete WIP PR, not fully finalized, but light review possible labels Dec 13, 2019
@Roasbeef Roasbeef marked this pull request as ready for review January 10, 2020 02:55
@Roasbeef
Copy link
Member Author

We have achieved full compilation everywhere!

@Roasbeef Roasbeef requested review from bhandras and removed request for halseth, joostjager and wpaulino January 10, 2020 02:56
@Roasbeef
Copy link
Member Author

Before this lands some form of this PR will need to land in btcwallet: btcsuite/btcwallet#671

@Roasbeef Roasbeef force-pushed the kv-abstraction branch 2 times, most recently from 33509e6 to d54fd5e Compare January 10, 2020 07:06
@Roasbeef Roasbeef added this to the 0.10.0 milestone Jan 14, 2020
@Roasbeef
Copy link
Member Author

The btcwallet PR has been merged, this PR is now ready for final review!

@Roasbeef
Copy link
Member Author

Fixed an issue that broke the tests due to passing in the wrong type (pretty subtle) into the DB within the contractcourt. The rule going forward is that if you're using the Batch call, then you need to pass in the kvdb.Backend instance rather than the channeldb.DB struct which embeds_ that interface.

@Roasbeef Roasbeef added the v0.10 label Jan 17, 2020
Copy link
Contributor

@joostjager joostjager left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a (PoC) implementation of the abstract interface for a different backend, to validate that this is an abstraction that is going to work before merging it?

@bhandras
Copy link
Collaborator

For context: I'm going to work on an etcd backend. Aggree with @joostjager fully. It would be nice to still treat this PR as a PoC as there are a large differences between etcd and bbolt (no buckets, cursors are different, transactions have limitations).

Copy link
Collaborator

@bhandras bhandras left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Continuing the review now that some of the previous questions are proven to work.


// RwBucket represents a bucket (a hierarchical structure within the database)
// that is allowed to perform both read and write operations.
type RwBucket = walletdb.ReadWriteBucket
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO, we should either use Rw or ReadWrite as a prefix for read-write APIs, but not mix them. I'm still in favor of reusing names from walletdb vs renaming, but Rw is indeed shorter (though looks inconsistent next to the Read prefix)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The type aliases can only modify top level exported types, and not methods as well.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What I meant is that there's a mix of Rw and ReadWrite prefixes in the type aliases which feels inconsistent.

_ "github.com/btcsuite/btcwallet/walletdb/bdb" // Import to register backend.
)

// Update opens a database read/write transaction and executes the function f
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One thing that bothers me a bit is that the comment refers to the function signature, yet we can't see it here.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

True we can't see it here, but it'll show up as normal on the rendered godoc (I think).

Copy link
Contributor

@cfromknecht cfromknecht left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

completed a full pass, overall changes look good. i agree with @bhandras's comments regarding bbolt's method names being easier/simpler to use, esp. re TopLevel and NestedBucket. only other comments are about mainly about naming for interface types, preferring R* and RW* due to brevity and consistency


// ReadTx represents a database transaction that can only be used for reads. If
// a database update must occur, use a RwTx.
type ReadTx = walletdb.ReadTx
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

naming suggestion: RTx and, similarly, RWTx? similar for cursor, bucket, etc. little strange that one type uses the full name while the other uses an abbreviation

go.mod Outdated
@@ -44,6 +44,7 @@ require (
github.com/rogpeppe/fastuuid v1.2.0 // indirect
github.com/tv42/zbase32 v0.0.0-20160707012821-501572607d02
github.com/urfave/cli v1.18.0
go.etcd.io/bbolt v1.3.3
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no go.sum change?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

still no go.sum change? is there a reason?

@Roasbeef
Copy link
Member Author

Rebased to the latest version of master.

Copy link
Collaborator

@bhandras bhandras left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is ready. My only complaint is the mixing of names (Rw vs ReadWrite).
LGTM


// RwBucket represents a bucket (a hierarchical structure within the database)
// that is allowed to perform both read and write operations.
type RwBucket = walletdb.ReadWriteBucket
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What I meant is that there's a mix of Rw and ReadWrite prefixes in the type aliases which feels inconsistent.

@Roasbeef
Copy link
Member Author

Build is now green.

Copy link
Contributor

@cfromknecht cfromknecht left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

overall i think the naming could improve, but looks correct. LGTM as long as we commit to doing a rename at a later point. only one lingering question

go.mod Outdated
@@ -44,6 +44,7 @@ require (
github.com/rogpeppe/fastuuid v1.2.0 // indirect
github.com/tv42/zbase32 v0.0.0-20160707012821-501572607d02
github.com/urfave/cli v1.18.0
go.etcd.io/bbolt v1.3.3
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

still no go.sum change? is there a reason?

Roasbeef added 14 commits March 18, 2020 19:34
In this commit, we create a new package `kvdb`, which is meant to serve
as the basis for any future database abstractions within `lnd`. Rather
than directly use the `walletdb` package (which we base off of), we
instead use a series of type-aliases to re-type the fundamental
types/interfaces of the `walletdb` package. This lets us type
`kvdb.RwTx` instead of `walletdb.ReadWriteTransaction` everywhere.
Additionally, our usage of type-aliases is also intended to create an
easy pathway in the future wherein we can gradually re-defined or
re-implement these types to wean off of the `walletdb` package.
In this commit, we migrate all the code in `channeldb` to only reference
the new `kvdb` package rather than `bbolt` directly.

In many instances, we need to add two version to fetch a bucket as both
read and write when needed. As an example, we add a new
`fetchChanBucketRw` function. This function is identical to
`fetchChanBucket`, but it will be used to fetch the main channel bucket
for all _write_ transactions. We need a new method as you can pass a
write transaction where a read is accepted, but not the other way around
due to the stronger typing of the new `kvdb` package.
The explicit `bbolt` dep is gone, as we depend on `kvdb`, which is
actually `walletdb`, which has its own module that defines the proper
`bbolt` version.
@Roasbeef
Copy link
Member Author

still no go.sum change? is there a reason

If I build, then go go mod tidy, I get this diff:

diff --git a/go.mod b/go.mod
index 55e4fea1e..812f824fa 100644
--- a/go.mod
+++ b/go.mod
@@ -14,7 +14,6 @@ require (
 	github.com/btcsuite/btcwallet/walletdb v1.2.0
 	github.com/btcsuite/btcwallet/wtxmgr v1.0.0
 	github.com/btcsuite/fastsha256 v0.0.0-20160815193821-637e65642941
-	github.com/coreos/bbolt v1.3.3
 	github.com/davecgh/go-spew v1.1.1
 	github.com/go-errors/errors v1.0.1
 	github.com/golang/protobuf v1.3.1
@@ -45,7 +44,6 @@ require (
 	github.com/rogpeppe/fastuuid v1.2.0 // indirect
 	github.com/tv42/zbase32 v0.0.0-20160707012821-501572607d02
 	github.com/urfave/cli v1.18.0
-	go.etcd.io/bbolt v1.3.3
 	golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67
 	golang.org/x/net v0.0.0-20190206173232-65e2d4e15006
 	golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2
diff --git a/go.sum b/go.sum
index c2773b2e5..b8991183e 100644
--- a/go.sum
+++ b/go.sum
@@ -185,9 +185,6 @@ golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnf
 golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
 golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67 h1:ng3VDlRp5/DHpSWl02R4rM9I+8M2rhmsuLwAMmkLQWE=
 golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
-golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
-golang.org/x/crypto v0.0.0-20200109152110-61a87790db17 h1:nVJ3guKA9qdkEQ3TUdXI9QSINo2CUPM/cySEvw2w8I0=
-golang.org/x/crypto v0.0.0-20200109152110-61a87790db17/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
 golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
 golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
 golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
@@ -199,8 +196,6 @@ golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73r
 golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20190206173232-65e2d4e15006 h1:bfLnR+k0tq5Lqt6dflRLcZiz6UaXCMt3vhYJ1l4FQ80=
 golang.org/x/net v0.0.0-20190206173232-65e2d4e15006/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
-golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3 h1:0GoQqolDA55aaLxZyTzK/Y2ePZzZTUrRacwib7cNsYQ=
-golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
 golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
 golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -213,8 +208,6 @@ golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5h
 golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20190209173611-3b5209105503 h1:5SvYFrOM3W8Mexn9/oA44Ji7vhXAZQ9hiP+1Q/DMrWg=
 golang.org/x/sys v0.0.0-20190209173611-3b5209105503/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
-golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
-golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20190904154756-749cb33beabd h1:DBH9mDw0zluJT/R+nGuV3jWFWLFaHyYZWD4tOT+cjn0=
 golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=

See the last commit for the rationale.

Updated the types to always use Rw for ReadWrite.

@Roasbeef Roasbeef merged commit 4897b34 into lightningnetwork:master Mar 19, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
database Related to the database/storage of LND golang/build system Related to the go language and compiler incomplete WIP PR, not fully finalized, but light review possible
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants