starcoinorg / starcoin

Starcoin - A Move smart contract blockchain network that scales by layering
Apache License 2.0
1.38k stars 289 forks source link

[FlexiDag] The relationship store write the relationships in two steps leading to data inconsistent #4125

Open jackzhhuang opened 6 months ago

jackzhhuang commented 6 months ago

Bug Report

impl RelationsStore for DbRelationsStore {
    /// See `insert_batch` as well
    /// TODO: use one function with DbWriter for both this function and insert_batch
    fn insert(&self, hash: Hash, parents: BlockHashes) -> Result<(), StoreError> {
        if self.has(hash)? {
            return Err(StoreError::KeyAlreadyExists(hash.to_string()));
        }

        // Insert a new entry for `hash`
        self.parents_access
            .write(DirectDbWriter::new(&self.db), hash, parents.clone())?;

        // The new hash has no children yet
        self.children_access.write(
            DirectDbWriter::new(&self.db),
            hash,
            BlockHashes::new(Vec::new()),
        )?;

        // Update `children` for each parent
        for parent in parents.iter().cloned() {
            let mut children = (*self.get_children(parent)?).clone();
            children.push(hash);
            self.children_access.write(
                DirectDbWriter::new(&self.db),
                parent,
                BlockHashes::new(children),
            )?;
        }

        Ok(())
    }
}

self.parents_access.write and self.children_access.write are two steps.

The data might be inconsistent if self.children_access.write fails and self.parents_access.write succeeds.