fluree / ledger

Fluree ledger server source
GNU Affero General Public License v3.0
77 stars 8 forks source link

Ledger gets corrupted when multiple updates happen on the same predicate in the same transaction #117

Open dmitri-safine opened 2 years ago

dmitri-safine commented 2 years ago

Observed Behaviour

Fluree ledger gets corrupted when multiple updates are happening on the same predicate as part of the same transaction, marking both updates as true in the produced block. After subsequent updates on the same predicate the query always returns one of the values from the multiple update transaction, ignoring any of the subsequent updates.

Expected Behaviour

  1. The transaction with multiple updates on the same predicate should fail or
  2. Only the last update out of multiple updates on the predicate in the transaction should be marked as true

Fluree versions:

Steps to reproduce

To reproduce follow these steps:

  1. Create a new ledger in Fluree Admin UI

  2. Create a new collection:

    [
    {
    "_id": "_collection",
    "name": "artwork"
    },
    {
    "_id": "_predicate",
    "name": "artwork/identifier",
    "index": true,
    "unique": true,
    "type": "string",
    "fullText": true
    },
    {
    "_id": "_predicate",
    "name": "artwork/title",
    "type": "string",
    "unique": false,
    "fullText": true,
    "index": true
    },
    {
    "_id": "_predicate",
    "name": "artwork/description",
    "type": "string",
    "unique": false,
    "fullText": true,
    "index": true
    }
    ]
  3. Insert records in the collection

    
    [
    {
    "_id": "artwork$1",
    "identifier": "1",
    "title": "Artwork 1",
    "description": "This is artwork 1"
    },
    {
    "_id": "artwork$2",
    "identifier": "2",
    "title": "Artwork 2",
    "description": "This is artwork 2"
    },
    {
    "_id": "artwork$3",
    "identifier": "3",
    "title": "Artwork 3",
    "description": "This is artwork 3"
    }

]

4. Get subject ID from one of the entries

5. Update title on one entity in the collection multiple times as part of the same transaction

[ { "_id": 351843720888320, "title": "Artwork 1 Updated" }, { "_id": 351843720888320, "title": "Artwork 1 Updated Again" } ]

6. Observe as the returned flakes result in both updates are marked as 'true'

"flakes": [ [ 351843720888320, 1002, "Artwork 1", -7, false, null ], [ 351843720888320, 1002, "Artwork 1 Updated", -7, true, null ], [ 351843720888320, 1002, "Artwork 1 Updated Again", -7, true, null ],

7. Query this entity and observe how it returns the first of the updates

{ "select": [ "*" ], "from": 351843720888320 }

[ { "_id": 351843720888320, "artwork/identifier": "1", "artwork/title": "Artwork 1 Updated", "artwork/description": "This is artwork 1" } ]

8. Perform  update again 

[ { "_id": 351843720888320, "title": "Artwork 1 Updated after multiple update" } ]

9. Observe how the transaction returns status 200 with the following flakes: 

"flakes": [ [ 351843720888320, 1002, "Artwork 1 Updated Again", -9, false, null ], [ 351843720888320, 1002, "Artwork 1 Updated after multiple update", -9, true, null ] ]

10. Notice how it replaced the second update in the list of multiple updates with 'false' 

11. Query the entity again and see how it returns the first value from the multiple updates, ignoring the latest update performed on the predicate

{ "select": [ "*" ], "from": 351843720888320 }

[ { "_id": 351843720888320, "artwork/identifier": "1", "artwork/title": "Artwork 1 Updated", "artwork/description": "This is artwork 1" } ]


12. Now doesn't matter how many times you'll be updating value on this predicate, the update transactions will be returning status 200, but value will always be locked on "Artwork 1 Updated" value. 
ldw1007 commented 2 years ago

Internal tracking purposes: FC-1322