From 1437a5d01940bbf9474632656f2e56f9d92fdbbc Mon Sep 17 00:00:00 2001 From: Erik de Castro Lopo Date: Tue, 20 Oct 2020 15:23:12 +1100 Subject: [PATCH] db-sync: Fix pool_id column in reward table The 'pool_id' in the 'reward' table is obtained by querying the 'delegation' table, and that query ordered the results by 'active_epoch_no'. However, for the case where two delegation (or pool update) certificates for the same address (or pool) are registered in the same epoch, this query can be incorrect. The fix is join with the 'block' table and order by the descending value of the 'slot_no' field. Closes: https://github.com/input-output-hk/cardano-db-sync/issues/361 --- .../src/Cardano/DbSync/Era/Shelley/Query.hs | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/cardano-db-sync/src/Cardano/DbSync/Era/Shelley/Query.hs b/cardano-db-sync/src/Cardano/DbSync/Era/Shelley/Query.hs index 1c5bf59e1..8c1a3e228 100644 --- a/cardano-db-sync/src/Cardano/DbSync/Era/Shelley/Query.hs +++ b/cardano-db-sync/src/Cardano/DbSync/Era/Shelley/Query.hs @@ -62,21 +62,29 @@ queryStakeAddress addr = do -- query catches this situation. queryStakeAddressAndPool :: MonadIO m => Word64 -> ByteString -> ReaderT SqlBackend m (Either LookupFail (StakeAddressId, PoolHashId)) queryStakeAddressAndPool epoch addr = do - res <- select . from $ \ (saddr `InnerJoin` dlg) -> do + res <- select . from $ \ (saddr `InnerJoin` dlg `InnerJoin` tx `InnerJoin` blk) -> do + on (blk ^. BlockId ==. tx ^. TxBlock) + on (dlg ^. DelegationTxId ==. tx ^. TxId) on (saddr ^. StakeAddressId ==. dlg ^. DelegationAddrId) where_ (saddr ^. StakeAddressHashRaw ==. val addr) where_ (dlg ^. DelegationActiveEpochNo <=. val epoch) - orderBy [desc (dlg ^. DelegationActiveEpochNo)] + -- Need to order by BlockSlotNo descending for correct behavior when there are two + -- or more delegation certificates in a single epoch. + orderBy [desc (blk ^. BlockSlotNo)] pure (saddr ^. StakeAddressId, dlg ^. DelegationPoolHashId) maybe queryPool (pure . Right . unValue2) (listToMaybe res) where queryPool :: MonadIO m => ReaderT SqlBackend m (Either LookupFail (StakeAddressId, PoolHashId)) queryPool = do - res <- select . from $ \ (saddr `InnerJoin` pu) -> do + res <- select . from $ \ (saddr `InnerJoin` pu `InnerJoin` tx `InnerJoin` blk) -> do + on (blk ^. BlockId ==. tx ^. TxBlock) + on (pu ^. PoolUpdateRegisteredTxId ==. tx ^. TxId) on (saddr ^. StakeAddressId ==. pu ^. PoolUpdateRewardAddrId) where_ (saddr ^. StakeAddressHashRaw ==. val addr) where_ (pu ^. PoolUpdateActiveEpochNo <=. val epoch) - orderBy [desc (pu ^. PoolUpdateActiveEpochNo)] + -- Need to order by BlockSlotNo descending for correct behavior when there are two + -- or more pool update certificates in a single epoch. + orderBy [desc (blk ^. BlockSlotNo)] pure (saddr ^. StakeAddressId, pu ^. PoolUpdateHashId) pure $ maybeToEither (DbLookupMessage $ "StakeAddressAndPool " <> renderByteArray addr) unValue2 (listToMaybe res) @@ -112,6 +120,9 @@ queryStakeAddressRef addr = where_ (blk ^. BlockSlotNo ==. just (val slot)) where_ (tx ^. TxBlockIndex ==. val (fromIntegral txIx)) where_ (dlg ^. DelegationCertIndex ==. val (fromIntegral certIx)) + -- Need to order by BlockSlotNo descending for correct behavior when there are two + -- or more delegation certificates in a single epoch. + orderBy [desc (blk ^. BlockSlotNo)] pure (dlg ^. DelegationAddrId) pure $ unValue <$> listToMaybe res