Skip to content

Appending changesets to Store after opening causes overwriting #1517

@KnowWhoami

Description

@KnowWhoami

Describe the bug

  • let's say a Store instance initially contains changeset1 stored in its file.

    pub struct Store<C>

  • Then after opening the store instance using Store::open and appending a new changeset (changeset2) using append_changeset, the store will only contain changeset2, not changeset1 + changeset2.

pub fn open<P>(magic: &[u8], file_path: P) -> Result<Self, FileError>

pub fn append_changeset(&mut self, changeset: &C) -> Result<(), io::Error> {

To Reproduce

  #[test]
   fn test() {
       let temp_dir = tempfile::tempdir().unwrap();
       let file_path = temp_dir.path().join("db_file");
       let changeset1 = BTreeSet::from(["hello".to_string(), "world".to_string()]);
       let changeset2 = BTreeSet::from(["got the error".to_string()]);

       {
           // create new  db
           let mut db = Store::<TestChangeSet>::create_new(&TEST_MAGIC_BYTES, &file_path)
               .expect("must create");

           // append first changeset to db
           db.append_changeset(&changeset1).expect("must succeed");
       }

       {
           // open db
           let mut db = Store::<TestChangeSet>::open_or_create_new(&TEST_MAGIC_BYTES, &file_path)
               .expect("failed to load db");

           // now append the second changeset
           db.append_changeset(&changeset2).expect("must succeed");

           // Retrieve stored changesets from the database
           let stored_changesets = db
               .aggregate_changesets()
               .expect("must succeed")
               .expect("must succeed");

           // expected changeset must  be changeset2 + changeset1
           let mut expected_changeset = changeset2.clone();
           expected_changeset.extend(changeset1);

           // Assert that stored_changesets matches changeset2 but not expected_changeset
           assert_eq!(stored_changesets, changeset2);
           assert_ne!(stored_changesets, expected_changeset);
       }

       // Reason:
       //
       // On loading the pre-existing store instance,
       // it contains all the pre-appended changesets but the file pointer is positioned back to 12
       // i.e till the size of TEST_MAGIC_BYTES array.
       // thus on appending any new changeset to db -> it overwrites those past changesets
       // thus only contain the latest changeset.

       // Open the store again to verify file pointer position at the end of the file
       let mut db =
           Store::<TestChangeSet>::open(&TEST_MAGIC_BYTES, &file_path).expect("failed to load db");

       // get the current position of file pointer just after loading store
       let current_pointer = db.db_file.stream_position().expect("must suceed");

       assert_eq!(current_pointer, 12);

       // end pointer for the loaded db
       let expected_pointer = db.db_file.seek(SeekFrom::End(0)).expect("must succeed");

       // both doesn't match
       assert_ne!(current_pointer, expected_pointer);
   }

Expected behavior

  • On opening the store -> its file pointer must be set to end.

Build environment

  • BDK tag/commit: d99b3ef
  • OS+version: Fedora 37
  • Rust/Cargo version: rustc 1.81.0-nightly (f21554f7f 2024-06-08)
  • Rust/Cargo target: nightly-2024-06-09-x86_64-unknown-linux-gnu

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Type

No type

Projects

Status

Done

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions