Abitrary persistence for wallet#771
Conversation
67ca081 to
174128a
Compare
27d2cb7 to
62cab2b
Compare
|
Should be ready to go. The integration tests ensure SQL still works. I may implement a simple database in Swift or Python just to ensure the roundtrips are okay. Otherwise, I think this approach is pretty nifty, as the performance should be the same for SQL users. |
66eab40 to
1757bdb
Compare
I'd def love to see this for Swift, and could help be another tester when you implement for anything you need |
|
Dummy implementation tested in python. Will check the round trip one. |
1757bdb to
e17bcc3
Compare
|
Do I understand correctly:
Do I have to merge multiple
|
You could also persist the total aggregate changeset, but this also seems to be a potential strategy and would certainly be easier.
Yes
This would not be too hard to implement manually, i.e. for the chain just update the heights and hashes, increase the descriptor indexes, add any new transactions, etc. However, this would change the API in the future if we wanted to add it later, so I think it is best to add the convenience methods like Because the |
6409d60 to
6915e2f
Compare
|
Tested the round trip and it works great, Including serialization to Json . |
6915e2f to
11dd559
Compare
|
Looking pretty great:
|
|
Awesome thanks for giving that a real world test. @andreasgriffin is putting together a Python test when he has some time, I will potentially work on a Swift test, but wouldn't have time for a couple weeks. If you have any interest in pushing an offline Swift test with custom persistence to my branch, that would be much appreciated! We would just want to make sure a round trip from bytes back to the change set can be implemented and the load/persist matches. |
The BDK `ChangeSet` offers some nice methods for building and working with changesets, particularly the `merge` method. Unfortunately to implement `merge` on `ChangeSet`, as well as the other constructors, we must convert the `ChangeSet` type to an object instead of a record. It is best to do this now instead of having to break the API in the future.
With the following approach we can accomplish two things at once: 1. Make it easy to add new Rust backends without sacrifing performance 2. Allow for arbitrary persistence accross the FFI To accomplish this we can differentiate between a native backend and a foreign backend. The foreign backend interacts with the FFI `ChangeSet`, whereas the native backend can just use the Rust changeset directly. Whenever a new backend is introduced in Rust, a new enum variant may simply be added to the `PersistenceType`. To build a Sqlite backend, or a foreign backend, the user will use the `Persister` structure. Abitrary persistence is allowed by implementing the `Persistence` trait. This was accomplished with no changes to bitcoindevkit#756. I hope 1. motivates this change thoroughly, as we expect BDK will add support for new backends in the future. I am also interested in the applications of 2., where a user might be able to do encrypted and cloud storage.
Changes named arguments in Swift as well as constructing the new `Persist` type with the usual sqlite database
4c60a4d to
1ce620f
Compare
|
I see python test added 1ce620f, nice! I'm not sure if the test is finalized or not yet, but I tested locally. Locally I got a failure on line 130 where it uses (not a python expert but) from what I'm seeing that syntax looks like its only available in Python 3.10+ (I was on Python 3.9.6 locally). I changed the code to Also overall I think this test didn't get picked up in CI on the PR because it didn't use the "offline" word in it to get picked up, I think we should have it in the offline tests because to me it qualifies for that conceptually, totally open to others opinions though? |
|
Good catch, I can add the offline prefix and fix that line tomorrow. Given how thorough the Python test is, I think we can keep the Swift and JVM with the default SQL options. Happy to accept other tests if they are added to my branch, but I think this should be finalized for review. |
1ce620f to
484d14a
Compare
|
Test is renamed with |
|
there might be a sorting issue of dicts in older python versions, that will let the test fail. I can investigate. |
484d14a to
8566315
Compare
Yeah, this is expected as the changeset uses hash maps, which can be initialized differently per two different dictionaries. I don't think the final assertion is necessary. The balance is equal if and only if the |
I think it is necessary, to check that persistence writing (not only initialization) works as expected. I'll look into making the sorting deterministic |
|
I fixed the issue in 2ac89a4 by using more sorting in the serializer. |
Here we check that an arbitrary persister can persist and load a wallet correctly. The test applies two unconfirmed transactions and asserts that a first wallet that persists the changes and a second wallet that loads from these changes will have the same values.
8566315 to
f81b8d4
Compare
|
f81b8d4 is updated to assert the two change sets are equal. Just in time for the weekend |
|
ACK f81b8d4 AWESOME |
Description
With the following approach we can accomplish two things at once:
To accomplish this we can differentiate between a native backend and a foreign backend. The foreign backend interacts with the FFI
ChangeSet, whereas the native backend can just use the Rust changeset directly. Whenever a new backend is introduced in Rust, a new enum variant may simply be added to thePersistenceType. To build a Sqlite backend, or a foreign backend, the user will use thePersisterstructure.Abitrary persistence is allowed by implementing the
Persistencetrait. This was accomplished with no changes to #756.I hope 1. motivates this change thoroughly, as we expect BDK will add support for new backends in the future. I am also interested in the applications of 2., where a user might be able to do encrypted and/or cloud storage.
Notes to the reviewers
We use an enum to allow for Rust backends to use Rust changesets directly. Otherwise we may convert them to FFI types. I've thought through many approaches, and I am convinced this is the most robust.
Changelog notice
Persistertype, that includes the usual sqlite approachChecklists
All Submissions:
cargo fmtandcargo clippybefore committing