diff --git a/patches/api/Add-Destroy-Speed-API.patch b/patches/api/Add-Destroy-Speed-API.patch
index 8e33c0979e..add801eee5 100644
--- a/patches/api/Add-Destroy-Speed-API.patch
+++ b/patches/api/Add-Destroy-Speed-API.patch
@@ -58,10 +58,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +     *
 +     * @param itemStack {@link ItemStack} used to mine this Block
 +     * @return the speed that this Block will be mined by the given {@link ItemStack}
-+     * @deprecated the destroy speed of a block was never purely tied to an item stack. Since 1.21 enchantments
-+     * also use complex effects that require a consuming player to compute their effects, including mining efficiency.
++     * @apiNote this method assumes default player state and hence, e.g., does not take into account changed
++     * player attributes or potion effects.
 +     */
-+    @Deprecated(forRemoval = true, since = "1.21")
 +    default float getDestroySpeed(final @NotNull ItemStack itemStack) {
 +        return this.getDestroySpeed(itemStack, false);
 +    }
@@ -74,10 +73,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +     * @param itemStack {@link ItemStack} used to mine this Block
 +     * @param considerEnchants true to look at enchants on the itemstack
 +     * @return the speed that this Block will be mined by the given {@link ItemStack}
-+     * @deprecated the destroy speed of a block was never purely tied to an item stack. Since 1.21 enchantments
-+     * also use complex effects that require a consuming player to compute their effects, including mining efficiency.
++     * @apiNote this method assumes default player state and hence, e.g., does not take into account changed
++     * player attributes or potion effects.
 +     */
-+    @Deprecated(forRemoval = true, since = "1.21")
 +    float getDestroySpeed(@NotNull ItemStack itemStack, boolean considerEnchants);
 +    // Paper end - destroy speed API
  }
diff --git a/patches/api/Block-Ticking-API.patch b/patches/api/Block-Ticking-API.patch
index ada40d87d3..7b9db3daba 100644
--- a/patches/api/Block-Ticking-API.patch
+++ b/patches/api/Block-Ticking-API.patch
@@ -55,7 +55,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 --- a/src/main/java/org/bukkit/block/data/BlockData.java
 +++ b/src/main/java/org/bukkit/block/data/BlockData.java
 @@ -0,0 +0,0 @@ public interface BlockData extends Cloneable {
-     @Deprecated(forRemoval = true, since = "1.21")
+      */
      float getDestroySpeed(@NotNull ItemStack itemStack, boolean considerEnchants);
      // Paper end - destroy speed API
 +
diff --git a/patches/server/Add-Destroy-Speed-API.patch b/patches/server/Add-Destroy-Speed-API.patch
index 656e804b6c..2da2e45246 100644
--- a/patches/server/Add-Destroy-Speed-API.patch
+++ b/patches/server/Add-Destroy-Speed-API.patch
@@ -5,6 +5,35 @@ Subject: [PATCH] Add Destroy Speed API
 
 Co-authored-by: Jake Potrebic <jake.m.potrebic@gmail.com>
 
+diff --git a/src/main/java/net/minecraft/world/entity/ai/attributes/AttributeInstance.java b/src/main/java/net/minecraft/world/entity/ai/attributes/AttributeInstance.java
+index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
+--- a/src/main/java/net/minecraft/world/entity/ai/attributes/AttributeInstance.java
++++ b/src/main/java/net/minecraft/world/entity/ai/attributes/AttributeInstance.java
+@@ -0,0 +0,0 @@ public class AttributeInstance {
+         double d = this.getBaseValue();
+ 
+         for (AttributeModifier attributeModifier : this.getModifiersOrEmpty(AttributeModifier.Operation.ADD_VALUE)) {
+-            d += attributeModifier.amount();
++            d += attributeModifier.amount(); // Paper - destroy speed API - diff on change
+         }
+ 
+         double e = d;
+ 
+         for (AttributeModifier attributeModifier2 : this.getModifiersOrEmpty(AttributeModifier.Operation.ADD_MULTIPLIED_BASE)) {
+-            e += d * attributeModifier2.amount();
++            e += d * attributeModifier2.amount(); // Paper - destroy speed API - diff on change
+         }
+ 
+         for (AttributeModifier attributeModifier3 : this.getModifiersOrEmpty(AttributeModifier.Operation.ADD_MULTIPLIED_TOTAL)) {
+-            e *= 1.0 + attributeModifier3.amount();
++            e *= 1.0 + attributeModifier3.amount(); // Paper - destroy speed API - diff on change
+         }
+ 
+-        return this.attribute.value().sanitizeValue(e);
++        return attribute.value().sanitizeValue(e); // Paper - destroy speed API - diff on change
+     }
+ 
+     private Collection<AttributeModifier> getModifiersOrEmpty(AttributeModifier.Operation operation) {
 diff --git a/src/main/java/org/bukkit/craftbukkit/block/data/CraftBlockData.java b/src/main/java/org/bukkit/craftbukkit/block/data/CraftBlockData.java
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 --- a/src/main/java/org/bukkit/craftbukkit/block/data/CraftBlockData.java
@@ -20,20 +49,171 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +        net.minecraft.world.item.ItemStack nmsItemStack = CraftItemStack.unwrap(itemStack);
 +        float speed = nmsItemStack.getDestroySpeed(this.state);
 +        if (speed > 1.0F && considerEnchants) {
-+            final net.minecraft.core.Holder<net.minecraft.world.item.enchantment.Enchantment> efficiencyHolder = net.minecraft.server.MinecraftServer
-+                .getServer()
-+                .registryAccess()
-+                .registryOrThrow(net.minecraft.core.registries.Registries.ENCHANTMENT)
-+                .getHolderOrThrow(net.minecraft.world.item.enchantment.Enchantments.EFFICIENCY);
++            final net.minecraft.core.Holder<net.minecraft.world.entity.ai.attributes.Attribute> attribute = net.minecraft.world.entity.ai.attributes.Attributes.MINING_EFFICIENCY;
++            // Logic sourced from AttributeInstance#calculateValue
++            final double initialBaseValue = attribute.value().getDefaultValue();
++            final org.apache.commons.lang3.mutable.MutableDouble modifiedBaseValue = new org.apache.commons.lang3.mutable.MutableDouble(initialBaseValue);
++            final org.apache.commons.lang3.mutable.MutableDouble baseValMul = new org.apache.commons.lang3.mutable.MutableDouble(1);
++            final org.apache.commons.lang3.mutable.MutableDouble totalValMul = new org.apache.commons.lang3.mutable.MutableDouble(1);
 +
-+            final int enchantLevel = net.minecraft.world.item.enchantment.EnchantmentHelper.getItemEnchantmentLevel(
-+                efficiencyHolder, nmsItemStack
++            net.minecraft.world.item.enchantment.EnchantmentHelper.forEachModifier(
++                nmsItemStack, net.minecraft.world.entity.EquipmentSlot.MAINHAND, (attributeHolder, attributeModifier) -> {
++                    switch (attributeModifier.operation()) {
++                        case ADD_VALUE -> modifiedBaseValue.add(attributeModifier.amount());
++                        case ADD_MULTIPLIED_BASE -> baseValMul.add(attributeModifier.amount());
++                        case ADD_MULTIPLIED_TOTAL -> totalValMul.setValue(totalValMul.doubleValue() * (1D + attributeModifier.amount()));
++                    }
++                }
 +            );
-+            if (enchantLevel > 0) {
-+                speed += enchantLevel * enchantLevel + 1;
-+            }
++
++            final double actualModifier = modifiedBaseValue.doubleValue() * baseValMul.doubleValue() * totalValMul.doubleValue();
++
++            speed += (float) attribute.value().sanitizeValue(actualModifier);
 +        }
 +        return speed;
 +    }
 +    // Paper end - destroy speed API
  }
+diff --git a/src/test/java/io/papermc/paper/block/CraftBlockDataDestroySpeedTest.java b/src/test/java/io/papermc/paper/block/CraftBlockDataDestroySpeedTest.java
+new file mode 100644
+index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
+--- /dev/null
++++ b/src/test/java/io/papermc/paper/block/CraftBlockDataDestroySpeedTest.java
+@@ -0,0 +0,0 @@
++package io.papermc.paper.block;
++
++import java.util.List;
++import java.util.Optional;
++import net.minecraft.core.Holder;
++import net.minecraft.core.HolderSet;
++import net.minecraft.core.component.DataComponentMap;
++import net.minecraft.core.component.DataComponents;
++import net.minecraft.network.chat.Component;
++import net.minecraft.world.entity.EquipmentSlot;
++import net.minecraft.world.entity.EquipmentSlotGroup;
++import net.minecraft.world.entity.ai.attributes.AttributeInstance;
++import net.minecraft.world.entity.ai.attributes.AttributeModifier;
++import net.minecraft.world.entity.ai.attributes.Attributes;
++import net.minecraft.world.item.Items;
++import net.minecraft.world.item.enchantment.Enchantment;
++import net.minecraft.world.item.enchantment.EnchantmentEffectComponents;
++import net.minecraft.world.item.enchantment.EnchantmentHelper;
++import net.minecraft.world.item.enchantment.ItemEnchantments;
++import net.minecraft.world.item.enchantment.LevelBasedValue;
++import net.minecraft.world.item.enchantment.effects.EnchantmentAttributeEffect;
++import net.minecraft.world.level.block.Blocks;
++import net.minecraft.world.level.block.state.BlockState;
++import org.bukkit.craftbukkit.block.data.CraftBlockData;
++import org.bukkit.craftbukkit.inventory.CraftItemStack;
++import org.bukkit.inventory.ItemStack;
++import org.bukkit.support.AbstractTestingBase;
++import org.bukkit.util.Vector;
++import org.jetbrains.annotations.NotNull;
++import org.junit.jupiter.api.Assertions;
++import org.junit.jupiter.api.Test;
++
++import static net.minecraft.resources.ResourceLocation.fromNamespaceAndPath;
++
++/**
++ * CraftBlockData's {@link org.bukkit.craftbukkit.block.data.CraftBlockData#getDestroySpeed(ItemStack, boolean)}
++ * uses a reimplementation of AttributeValue without any map to avoid attribute instance allocation and mutation
++ * for 0 gain.
++ * <p>
++ * This test is responsible for ensuring that said logic emits the expected destroy speed under heavy attribute
++ * modifier use.
++ */
++public class CraftBlockDataDestroySpeedTest extends AbstractTestingBase {
++
++    @Test
++    public void testCorrectEnchantmentDestroySpeedComputation() {
++        // Construct fake enchantment that has *all and multiple of* operations
++        final Enchantment speedEnchantment = speedEnchantment();
++        final BlockState blockStateToMine = Blocks.STONE.defaultBlockState();
++
++        final ItemEnchantments.Mutable mutable = new ItemEnchantments.Mutable(ItemEnchantments.EMPTY);
++        mutable.set(Holder.direct(speedEnchantment), 1);
++
++        final net.minecraft.world.item.ItemStack itemStack = new net.minecraft.world.item.ItemStack(Items.DIAMOND_PICKAXE);
++        itemStack.set(DataComponents.ENCHANTMENTS, mutable.toImmutable());
++
++        // Compute expected value by running the entire attribute instance chain
++        final AttributeInstance dummyInstance = new AttributeInstance(Attributes.MINING_EFFICIENCY, $ -> {
++        });
++        EnchantmentHelper.forEachModifier(itemStack, EquipmentSlot.MAINHAND, (attributeHolder, attributeModifier) -> {
++            if (attributeHolder.is(Attributes.MINING_EFFICIENCY)) dummyInstance.addTransientModifier(attributeModifier);
++        });
++
++        final double toolSpeed = itemStack.getDestroySpeed(blockStateToMine);
++        final double expectedSpeed = toolSpeed <= 1.0F ? toolSpeed : toolSpeed + dummyInstance.getValue();
++
++        // API stack + computation
++        final CraftItemStack craftMirror = CraftItemStack.asCraftMirror(itemStack);
++        final CraftBlockData data = CraftBlockData.createData(blockStateToMine);
++        final float actualSpeed = data.getDestroySpeed(craftMirror, true);
++
++        Assertions.assertEquals(expectedSpeed, actualSpeed, Vector.getEpsilon());
++    }
++
++    /**
++     * Complex enchantment that holds attribute modifiers for the mining efficiency.
++     * The enchantment holds 2 of each operation to also ensure that such behaviour works correctly.
++     *
++     * @return the enchantment.
++     */
++    private static @NotNull Enchantment speedEnchantment() {
++        return new Enchantment(
++            Component.empty(),
++            new Enchantment.EnchantmentDefinition(
++                HolderSet.empty(),
++                Optional.empty(),
++                0, 0,
++                Enchantment.constantCost(0),
++                Enchantment.constantCost(0),
++                0,
++                List.of(EquipmentSlotGroup.ANY)
++            ),
++            HolderSet.empty(),
++            DataComponentMap.builder()
++                .set(EnchantmentEffectComponents.ATTRIBUTES, List.of(
++                    new EnchantmentAttributeEffect(
++                        fromNamespaceAndPath("paper", "base1"),
++                        Attributes.MINING_EFFICIENCY,
++                        LevelBasedValue.constant(1),
++                        AttributeModifier.Operation.ADD_VALUE
++                    ),
++                    new EnchantmentAttributeEffect(
++                        fromNamespaceAndPath("paper", "base2"),
++                        Attributes.MINING_EFFICIENCY,
++                        LevelBasedValue.perLevel(3),
++                        AttributeModifier.Operation.ADD_VALUE
++                    ),
++                    new EnchantmentAttributeEffect(
++                        fromNamespaceAndPath("paper", "base-mul1"),
++                        Attributes.MINING_EFFICIENCY,
++                        LevelBasedValue.perLevel(7),
++                        AttributeModifier.Operation.ADD_MULTIPLIED_BASE
++                    ),
++                    new EnchantmentAttributeEffect(
++                        fromNamespaceAndPath("paper", "base-mul2"),
++                        Attributes.MINING_EFFICIENCY,
++                        LevelBasedValue.constant(10),
++                        AttributeModifier.Operation.ADD_MULTIPLIED_BASE
++                    ),
++                    new EnchantmentAttributeEffect(
++                        fromNamespaceAndPath("paper", "total-mul1"),
++                        Attributes.MINING_EFFICIENCY,
++                        LevelBasedValue.constant(.2f),
++                        AttributeModifier.Operation.ADD_MULTIPLIED_TOTAL
++                    ),
++                    new EnchantmentAttributeEffect(
++                        fromNamespaceAndPath("paper", "total-mul2"),
++                        Attributes.MINING_EFFICIENCY,
++                        LevelBasedValue.constant(-.5F),
++                        AttributeModifier.Operation.ADD_MULTIPLIED_TOTAL
++                    )
++                ))
++                .build()
++        );
++    }
++
++}