Kernels:
Trusted publisher
Uploaded using `kernel-builder`.
Browse files- build/torch-cuda/_ops.py +1 -1
- build/torch-cuda/_ops_compat.py +0 -18
- build/torch-cuda/layer_norm.py +139 -70
- build/torch-cuda/metadata.json +14 -4
- build/torch-cuda/metadata.json.sigstore +1 -1
build/torch-cuda/_ops.py
CHANGED
|
@@ -22,7 +22,7 @@ def get_backend() -> str:
|
|
| 22 |
|
| 23 |
def _find_ops_name() -> str:
|
| 24 |
kernel_name = "flash_attn_ops"
|
| 25 |
-
unique_id = "
|
| 26 |
backend = get_backend()
|
| 27 |
return f"_{kernel_name}_{backend}_{unique_id}"
|
| 28 |
|
|
|
|
| 22 |
|
| 23 |
def _find_ops_name() -> str:
|
| 24 |
kernel_name = "flash_attn_ops"
|
| 25 |
+
unique_id = "8a730d9"
|
| 26 |
backend = get_backend()
|
| 27 |
return f"_{kernel_name}_{backend}_{unique_id}"
|
| 28 |
|
build/torch-cuda/_ops_compat.py
DELETED
|
@@ -1,18 +0,0 @@
|
|
| 1 |
-
"""Compatibility helpers for op namespacing in source and built layouts.
|
| 2 |
-
|
| 3 |
-
In the built (Hub) layout, kernel-builder generates an `_ops` module that
|
| 4 |
-
exposes `add_op_namespace_prefix`, which prefixes op names with a unique,
|
| 5 |
-
build-hashed namespace so custom ops never collide across kernels/versions. When
|
| 6 |
-
running directly from source there is no generated `_ops`, so we fall back to a
|
| 7 |
-
fixed namespace.
|
| 8 |
-
"""
|
| 9 |
-
|
| 10 |
-
try:
|
| 11 |
-
from ._ops import add_op_namespace_prefix as _generated_add_op_namespace_prefix
|
| 12 |
-
except ImportError:
|
| 13 |
-
def _generated_add_op_namespace_prefix(name: str) -> str:
|
| 14 |
-
return name if "::" in name else f"flash_attn_ops::{name}"
|
| 15 |
-
|
| 16 |
-
|
| 17 |
-
def add_op_namespace_prefix(name: str) -> str:
|
| 18 |
-
return _generated_add_op_namespace_prefix(name)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
build/torch-cuda/layer_norm.py
CHANGED
|
@@ -7,18 +7,17 @@
|
|
| 7 |
# The models we train have hidden dim up to 8k anyway (e.g. Llama 70B), so this is fine.
|
| 8 |
|
| 9 |
import math
|
| 10 |
-
from typing import
|
| 11 |
|
| 12 |
import torch
|
| 13 |
import torch.nn.functional as F
|
| 14 |
-
from torch import Tensor
|
| 15 |
-
|
| 16 |
import triton
|
| 17 |
import triton.language as tl
|
|
|
|
| 18 |
|
| 19 |
-
from .
|
| 20 |
from .utils.library import triton_op
|
| 21 |
-
from .
|
| 22 |
|
| 23 |
|
| 24 |
def maybe_contiguous_lastdim(x):
|
|
@@ -40,9 +39,17 @@ def triton_autotune_configs():
|
|
| 40 |
warp_size = 32
|
| 41 |
if torch.cuda.is_available():
|
| 42 |
warp_size = getattr(torch.cuda.get_device_properties(torch.cuda.current_device()), "warp_size", 32)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 43 |
# Autotune for warp counts which are powers of 2 and do not exceed thread per block limit
|
| 44 |
-
return [
|
| 45 |
-
|
|
|
|
|
|
|
|
|
|
| 46 |
# return [triton.Config({}, num_warps=8)]
|
| 47 |
|
| 48 |
|
|
@@ -94,9 +101,9 @@ def layer_norm_ref(
|
|
| 94 |
x = x + x1
|
| 95 |
if residual is not None:
|
| 96 |
x = (x + residual).to(x.dtype)
|
| 97 |
-
out = F.layer_norm(
|
| 98 |
-
dtype
|
| 99 |
-
)
|
| 100 |
if weight1 is None:
|
| 101 |
return out if not prenorm else (out, x)
|
| 102 |
else:
|
|
@@ -155,19 +162,30 @@ def rms_norm_ref(
|
|
| 155 |
if residual is not None:
|
| 156 |
x = (x + residual).to(x.dtype)
|
| 157 |
rstd = 1 / torch.sqrt((x.square()).mean(dim=-1, keepdim=True) + eps)
|
| 158 |
-
out = ((x * rstd * weight) + bias if bias is not None else (x * rstd * weight)).to(
|
|
|
|
|
|
|
| 159 |
if weight1 is None:
|
| 160 |
return out if not prenorm else (out, x)
|
| 161 |
else:
|
| 162 |
-
out1 = (
|
| 163 |
-
|
| 164 |
-
)
|
| 165 |
return (out, out1) if not prenorm else (out, out1, x)
|
| 166 |
|
| 167 |
|
| 168 |
@triton.autotune(
|
| 169 |
configs=triton_autotune_configs(),
|
| 170 |
-
key=[
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 171 |
)
|
| 172 |
# torch compile doesn't like triton.heuristics, so we set these manually when calling the kernel
|
| 173 |
# @triton.heuristics({"HAS_BIAS": lambda args: args["B"] is not None})
|
|
@@ -237,7 +255,9 @@ def _layer_norm_fwd_1pass_kernel(
|
|
| 237 |
if HAS_DROPOUT:
|
| 238 |
# Compute dropout mask
|
| 239 |
# 7 rounds is good enough, and reduces register pressure
|
| 240 |
-
keep_mask =
|
|
|
|
|
|
|
| 241 |
x = tl.where(keep_mask, x / (1.0 - dropout_p), 0.0)
|
| 242 |
if STORE_DROPOUT_MASK:
|
| 243 |
tl.store(DROPOUT_MASK + row * N + cols, keep_mask, mask=cols < N)
|
|
@@ -250,7 +270,8 @@ def _layer_norm_fwd_1pass_kernel(
|
|
| 250 |
# Compute dropout mask
|
| 251 |
# 7 rounds is good enough, and reduces register pressure
|
| 252 |
keep_mask = (
|
| 253 |
-
tl.rand(tl.load(SEEDS + M + row).to(tl.uint32), cols, n_rounds=7)
|
|
|
|
| 254 |
)
|
| 255 |
x1 = tl.where(keep_mask, x1 / (1.0 - dropout_p), 0.0)
|
| 256 |
if STORE_DROPOUT_MASK:
|
|
@@ -309,7 +330,7 @@ def _layer_norm_fwd(
|
|
| 309 |
is_rms_norm: bool = False,
|
| 310 |
return_dropout_mask: bool = False,
|
| 311 |
out: Optional[Tensor] = None,
|
| 312 |
-
residual_out: Optional[Tensor] = None
|
| 313 |
) -> (Tensor, Tensor, Tensor, Tensor, Tensor, Tensor, Tensor, Tensor):
|
| 314 |
# Need to wrap to handle the case where residual_out is a alias of x, which makes torch.library
|
| 315 |
# and torch.compile unhappy. Also allocate memory for out and residual_out if they are None
|
|
@@ -355,8 +376,11 @@ def _layer_norm_fwd(
|
|
| 355 |
|
| 356 |
# [2025-04-28] torch.library.triton_op ignores the schema argument, but here we need the schema
|
| 357 |
# since we're returning a tuple of tensors
|
| 358 |
-
@triton_op(
|
| 359 |
-
|
|
|
|
|
|
|
|
|
|
| 360 |
def _layer_norm_fwd_impl(
|
| 361 |
x: Tensor,
|
| 362 |
weight: Tensor,
|
|
@@ -372,7 +396,7 @@ def _layer_norm_fwd_impl(
|
|
| 372 |
zero_centered_weight: bool = False,
|
| 373 |
is_rms_norm: bool = False,
|
| 374 |
return_dropout_mask: bool = False,
|
| 375 |
-
residual_out: Optional[Tensor] = None
|
| 376 |
) -> (Tensor, Tensor, Tensor, Tensor, Tensor, Tensor):
|
| 377 |
M, N = x.shape
|
| 378 |
assert x.stride(-1) == 1
|
|
@@ -407,7 +431,11 @@ def _layer_norm_fwd_impl(
|
|
| 407 |
assert y1.stride(-1) == 1
|
| 408 |
else:
|
| 409 |
y1 = None
|
| 410 |
-
mean =
|
|
|
|
|
|
|
|
|
|
|
|
|
| 411 |
rstd = torch.empty((M,), dtype=torch.float32, device=x.device)
|
| 412 |
if dropout_p > 0.0:
|
| 413 |
seeds = torch.randint(
|
|
@@ -475,7 +503,14 @@ def _layer_norm_fwd_impl(
|
|
| 475 |
|
| 476 |
@triton.autotune(
|
| 477 |
configs=triton_autotune_configs(),
|
| 478 |
-
key=[
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 479 |
)
|
| 480 |
# torch compile doesn't like triton.heuristics, so we set these manually when calling the kernel
|
| 481 |
# @triton.heuristics({"HAS_BIAS": lambda args: args["B"] is not None})
|
|
@@ -609,14 +644,18 @@ def _layer_norm_bwd_kernel(
|
|
| 609 |
if HAS_DX1:
|
| 610 |
if HAS_DROPOUT:
|
| 611 |
keep_mask = (
|
| 612 |
-
tl.rand(tl.load(SEEDS + M + row).to(tl.uint32), cols, n_rounds=7)
|
|
|
|
| 613 |
)
|
| 614 |
dx1 = tl.where(keep_mask, dx / (1.0 - dropout_p), 0.0)
|
| 615 |
else:
|
| 616 |
dx1 = dx
|
| 617 |
tl.store(DX1 + cols, dx1, mask=mask)
|
| 618 |
if HAS_DROPOUT:
|
| 619 |
-
keep_mask =
|
|
|
|
|
|
|
|
|
|
| 620 |
dx = tl.where(keep_mask, dx / (1.0 - dropout_p), 0.0)
|
| 621 |
if HAS_ROWSCALE:
|
| 622 |
rowscale = tl.load(ROWSCALE + row).to(tl.float32)
|
|
@@ -699,11 +738,12 @@ def _layer_norm_bwd(
|
|
| 699 |
return dx, dw, db, dresidual_in, dx1, dw1, db1, y
|
| 700 |
|
| 701 |
|
| 702 |
-
|
| 703 |
-
|
| 704 |
-
|
| 705 |
-
|
| 706 |
-
|
|
|
|
| 707 |
def _layer_norm_bwd_impl(
|
| 708 |
dy: Tensor,
|
| 709 |
x: Tensor,
|
|
@@ -770,9 +810,15 @@ def _layer_norm_bwd_impl(
|
|
| 770 |
else None
|
| 771 |
)
|
| 772 |
dx1 = torch.empty_like(dx) if (has_x1 and dropout_p > 0.0) else None
|
| 773 |
-
y =
|
|
|
|
|
|
|
|
|
|
|
|
|
| 774 |
if recompute_output:
|
| 775 |
-
assert weight1 is None,
|
|
|
|
|
|
|
| 776 |
|
| 777 |
# Less than 64KB per feature: enqueue fused kernel
|
| 778 |
MAX_FUSED_SIZE = 65536 // x.element_size()
|
|
@@ -849,7 +895,6 @@ def _layer_norm_bwd_impl(
|
|
| 849 |
|
| 850 |
|
| 851 |
class LayerNormFn(torch.autograd.Function):
|
| 852 |
-
|
| 853 |
@staticmethod
|
| 854 |
def forward(
|
| 855 |
ctx,
|
|
@@ -870,14 +915,16 @@ class LayerNormFn(torch.autograd.Function):
|
|
| 870 |
return_dropout_mask=False,
|
| 871 |
out_dtype=None,
|
| 872 |
out=None,
|
| 873 |
-
residual_out=None
|
| 874 |
):
|
| 875 |
x_shape_og = x.shape
|
| 876 |
# reshape input data into 2D tensor
|
| 877 |
x = maybe_contiguous_lastdim(x.reshape(-1, x.shape[-1]))
|
| 878 |
if residual is not None:
|
| 879 |
assert residual.shape == x_shape_og
|
| 880 |
-
residual = maybe_contiguous_lastdim(
|
|
|
|
|
|
|
| 881 |
if x1 is not None:
|
| 882 |
assert x1.shape == x_shape_og
|
| 883 |
assert rowscale is None, "rowscale is not supported with parallel LayerNorm"
|
|
@@ -897,24 +944,26 @@ class LayerNormFn(torch.autograd.Function):
|
|
| 897 |
out = out.reshape(-1, out.shape[-1])
|
| 898 |
if residual_out is not None:
|
| 899 |
residual_out = residual_out.reshape(-1, residual_out.shape[-1])
|
| 900 |
-
y, y1, mean, rstd, residual_out, seeds, dropout_mask, dropout_mask1 =
|
| 901 |
-
|
| 902 |
-
|
| 903 |
-
|
| 904 |
-
|
| 905 |
-
|
| 906 |
-
|
| 907 |
-
|
| 908 |
-
|
| 909 |
-
|
| 910 |
-
|
| 911 |
-
|
| 912 |
-
|
| 913 |
-
|
| 914 |
-
|
| 915 |
-
|
| 916 |
-
|
| 917 |
-
|
|
|
|
|
|
|
| 918 |
)
|
| 919 |
ctx.save_for_backward(
|
| 920 |
residual_out, weight, bias, weight1, bias1, rowscale, seeds, mean, rstd
|
|
@@ -930,9 +979,15 @@ class LayerNormFn(torch.autograd.Function):
|
|
| 930 |
ctx.zero_centered_weight = zero_centered_weight
|
| 931 |
y = y.reshape(x_shape_og)
|
| 932 |
y1 = y1.reshape(x_shape_og) if y1 is not None else None
|
| 933 |
-
residual_out =
|
| 934 |
-
|
| 935 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 936 |
if not return_dropout_mask:
|
| 937 |
if weight1 is None:
|
| 938 |
return y if not prenorm else (y, residual_out)
|
|
@@ -1030,7 +1085,7 @@ def layer_norm_fn(
|
|
| 1030 |
return_dropout_mask=False,
|
| 1031 |
out_dtype=None,
|
| 1032 |
out=None,
|
| 1033 |
-
residual_out=None
|
| 1034 |
):
|
| 1035 |
return LayerNormFn.apply(
|
| 1036 |
x,
|
|
@@ -1050,7 +1105,7 @@ def layer_norm_fn(
|
|
| 1050 |
return_dropout_mask,
|
| 1051 |
out_dtype,
|
| 1052 |
out,
|
| 1053 |
-
residual_out
|
| 1054 |
)
|
| 1055 |
|
| 1056 |
|
|
@@ -1071,7 +1126,7 @@ def rms_norm_fn(
|
|
| 1071 |
return_dropout_mask=False,
|
| 1072 |
out_dtype=None,
|
| 1073 |
out=None,
|
| 1074 |
-
residual_out=None
|
| 1075 |
):
|
| 1076 |
return LayerNormFn.apply(
|
| 1077 |
x,
|
|
@@ -1091,14 +1146,20 @@ def rms_norm_fn(
|
|
| 1091 |
return_dropout_mask,
|
| 1092 |
out_dtype,
|
| 1093 |
out,
|
| 1094 |
-
residual_out
|
| 1095 |
)
|
| 1096 |
|
| 1097 |
|
| 1098 |
class RMSNorm(torch.nn.Module):
|
| 1099 |
-
|
| 1100 |
-
|
| 1101 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1102 |
factory_kwargs = {"device": device, "dtype": dtype}
|
| 1103 |
super().__init__()
|
| 1104 |
self.eps = eps
|
|
@@ -1132,7 +1193,6 @@ class RMSNorm(torch.nn.Module):
|
|
| 1132 |
|
| 1133 |
|
| 1134 |
class LayerNormLinearFn(torch.autograd.Function):
|
| 1135 |
-
|
| 1136 |
@staticmethod
|
| 1137 |
@custom_fwd
|
| 1138 |
def forward(
|
|
@@ -1153,7 +1213,9 @@ class LayerNormLinearFn(torch.autograd.Function):
|
|
| 1153 |
x = maybe_contiguous_lastdim(x.reshape(-1, x.shape[-1]))
|
| 1154 |
if residual is not None:
|
| 1155 |
assert residual.shape == x_shape_og
|
| 1156 |
-
residual = maybe_contiguous_lastdim(
|
|
|
|
|
|
|
| 1157 |
norm_weight = norm_weight.contiguous()
|
| 1158 |
norm_bias = maybe_contiguous(norm_bias)
|
| 1159 |
residual_dtype = (
|
|
@@ -1167,17 +1229,23 @@ class LayerNormLinearFn(torch.autograd.Function):
|
|
| 1167 |
norm_bias,
|
| 1168 |
eps,
|
| 1169 |
residual,
|
| 1170 |
-
out_dtype=None
|
|
|
|
|
|
|
| 1171 |
residual_dtype=residual_dtype,
|
| 1172 |
is_rms_norm=is_rms_norm,
|
| 1173 |
)
|
| 1174 |
y = y.reshape(x_shape_og)
|
| 1175 |
-
dtype =
|
|
|
|
|
|
|
| 1176 |
linear_weight = linear_weight.to(dtype)
|
| 1177 |
linear_bias = linear_bias.to(dtype) if linear_bias is not None else None
|
| 1178 |
out = F.linear(y.to(linear_weight.dtype), linear_weight, linear_bias)
|
| 1179 |
# We don't store y, will be recomputed in the backward pass to save memory
|
| 1180 |
-
ctx.save_for_backward(
|
|
|
|
|
|
|
| 1181 |
ctx.x_shape_og = x_shape_og
|
| 1182 |
ctx.eps = eps
|
| 1183 |
ctx.is_rms_norm = is_rms_norm
|
|
@@ -1198,8 +1266,9 @@ class LayerNormLinearFn(torch.autograd.Function):
|
|
| 1198 |
assert dy.shape == x.shape
|
| 1199 |
if ctx.prenorm:
|
| 1200 |
dresidual = args[0]
|
| 1201 |
-
dresidual = maybe_contiguous_lastdim(
|
| 1202 |
-
|
|
|
|
| 1203 |
else:
|
| 1204 |
dresidual = None
|
| 1205 |
dx, dnorm_weight, dnorm_bias, dresidual_in, _, _, _, y = _layer_norm_bwd(
|
|
|
|
| 7 |
# The models we train have hidden dim up to 8k anyway (e.g. Llama 70B), so this is fine.
|
| 8 |
|
| 9 |
import math
|
| 10 |
+
from typing import List, Optional
|
| 11 |
|
| 12 |
import torch
|
| 13 |
import torch.nn.functional as F
|
|
|
|
|
|
|
| 14 |
import triton
|
| 15 |
import triton.language as tl
|
| 16 |
+
from torch import Tensor
|
| 17 |
|
| 18 |
+
from ._ops import add_op_namespace_prefix
|
| 19 |
from .utils.library import triton_op
|
| 20 |
+
from .utils.torch import custom_bwd, custom_fwd
|
| 21 |
|
| 22 |
|
| 23 |
def maybe_contiguous_lastdim(x):
|
|
|
|
| 39 |
warp_size = 32
|
| 40 |
if torch.cuda.is_available():
|
| 41 |
warp_size = getattr(torch.cuda.get_device_properties(torch.cuda.current_device()), "warp_size", 32)
|
| 42 |
+
warp_size = getattr(
|
| 43 |
+
torch.cuda.get_device_properties(torch.cuda.current_device()),
|
| 44 |
+
"warp_size",
|
| 45 |
+
32,
|
| 46 |
+
)
|
| 47 |
# Autotune for warp counts which are powers of 2 and do not exceed thread per block limit
|
| 48 |
+
return [
|
| 49 |
+
triton.Config({}, num_warps=warp_count)
|
| 50 |
+
for warp_count in [1, 2, 4, 8, 16, 32]
|
| 51 |
+
if warp_count * warp_size <= max_threads_per_block
|
| 52 |
+
]
|
| 53 |
# return [triton.Config({}, num_warps=8)]
|
| 54 |
|
| 55 |
|
|
|
|
| 101 |
x = x + x1
|
| 102 |
if residual is not None:
|
| 103 |
x = (x + residual).to(x.dtype)
|
| 104 |
+
out = F.layer_norm(
|
| 105 |
+
x.to(weight.dtype), x.shape[-1:], weight=weight, bias=bias, eps=eps
|
| 106 |
+
).to(dtype)
|
| 107 |
if weight1 is None:
|
| 108 |
return out if not prenorm else (out, x)
|
| 109 |
else:
|
|
|
|
| 162 |
if residual is not None:
|
| 163 |
x = (x + residual).to(x.dtype)
|
| 164 |
rstd = 1 / torch.sqrt((x.square()).mean(dim=-1, keepdim=True) + eps)
|
| 165 |
+
out = ((x * rstd * weight) + bias if bias is not None else (x * rstd * weight)).to(
|
| 166 |
+
dtype
|
| 167 |
+
)
|
| 168 |
if weight1 is None:
|
| 169 |
return out if not prenorm else (out, x)
|
| 170 |
else:
|
| 171 |
+
out1 = (
|
| 172 |
+
(x * rstd * weight1) + bias1 if bias1 is not None else (x * rstd * weight1)
|
| 173 |
+
).to(dtype)
|
| 174 |
return (out, out1) if not prenorm else (out, out1, x)
|
| 175 |
|
| 176 |
|
| 177 |
@triton.autotune(
|
| 178 |
configs=triton_autotune_configs(),
|
| 179 |
+
key=[
|
| 180 |
+
"N",
|
| 181 |
+
"HAS_RESIDUAL",
|
| 182 |
+
"STORE_RESIDUAL_OUT",
|
| 183 |
+
"IS_RMS_NORM",
|
| 184 |
+
"HAS_BIAS",
|
| 185 |
+
"HAS_X1",
|
| 186 |
+
"HAS_W1",
|
| 187 |
+
"HAS_B1",
|
| 188 |
+
],
|
| 189 |
)
|
| 190 |
# torch compile doesn't like triton.heuristics, so we set these manually when calling the kernel
|
| 191 |
# @triton.heuristics({"HAS_BIAS": lambda args: args["B"] is not None})
|
|
|
|
| 255 |
if HAS_DROPOUT:
|
| 256 |
# Compute dropout mask
|
| 257 |
# 7 rounds is good enough, and reduces register pressure
|
| 258 |
+
keep_mask = (
|
| 259 |
+
tl.rand(tl.load(SEEDS + row).to(tl.uint32), cols, n_rounds=7) > dropout_p
|
| 260 |
+
)
|
| 261 |
x = tl.where(keep_mask, x / (1.0 - dropout_p), 0.0)
|
| 262 |
if STORE_DROPOUT_MASK:
|
| 263 |
tl.store(DROPOUT_MASK + row * N + cols, keep_mask, mask=cols < N)
|
|
|
|
| 270 |
# Compute dropout mask
|
| 271 |
# 7 rounds is good enough, and reduces register pressure
|
| 272 |
keep_mask = (
|
| 273 |
+
tl.rand(tl.load(SEEDS + M + row).to(tl.uint32), cols, n_rounds=7)
|
| 274 |
+
> dropout_p
|
| 275 |
)
|
| 276 |
x1 = tl.where(keep_mask, x1 / (1.0 - dropout_p), 0.0)
|
| 277 |
if STORE_DROPOUT_MASK:
|
|
|
|
| 330 |
is_rms_norm: bool = False,
|
| 331 |
return_dropout_mask: bool = False,
|
| 332 |
out: Optional[Tensor] = None,
|
| 333 |
+
residual_out: Optional[Tensor] = None,
|
| 334 |
) -> (Tensor, Tensor, Tensor, Tensor, Tensor, Tensor, Tensor, Tensor):
|
| 335 |
# Need to wrap to handle the case where residual_out is a alias of x, which makes torch.library
|
| 336 |
# and torch.compile unhappy. Also allocate memory for out and residual_out if they are None
|
|
|
|
| 376 |
|
| 377 |
# [2025-04-28] torch.library.triton_op ignores the schema argument, but here we need the schema
|
| 378 |
# since we're returning a tuple of tensors
|
| 379 |
+
@triton_op(
|
| 380 |
+
add_op_namespace_prefix("layer_norm_fwd_impl"),
|
| 381 |
+
mutates_args={"out", "residual_out"},
|
| 382 |
+
schema="(Tensor x, Tensor weight, Tensor bias, float eps, Tensor(a!) out, Tensor? residual, Tensor? x1, Tensor? weight1, Tensor? bias1, float dropout_p, Tensor? rowscale, bool zero_centered_weight, bool is_rms_norm, bool return_dropout_mask, Tensor(a!)? residual_out) -> (Tensor y1, Tensor mean, Tensor rstd, Tensor seeds, Tensor dropout_mask, Tensor dropout_mask1)",
|
| 383 |
+
)
|
| 384 |
def _layer_norm_fwd_impl(
|
| 385 |
x: Tensor,
|
| 386 |
weight: Tensor,
|
|
|
|
| 396 |
zero_centered_weight: bool = False,
|
| 397 |
is_rms_norm: bool = False,
|
| 398 |
return_dropout_mask: bool = False,
|
| 399 |
+
residual_out: Optional[Tensor] = None,
|
| 400 |
) -> (Tensor, Tensor, Tensor, Tensor, Tensor, Tensor):
|
| 401 |
M, N = x.shape
|
| 402 |
assert x.stride(-1) == 1
|
|
|
|
| 431 |
assert y1.stride(-1) == 1
|
| 432 |
else:
|
| 433 |
y1 = None
|
| 434 |
+
mean = (
|
| 435 |
+
torch.empty((M,), dtype=torch.float32, device=x.device)
|
| 436 |
+
if not is_rms_norm
|
| 437 |
+
else None
|
| 438 |
+
)
|
| 439 |
rstd = torch.empty((M,), dtype=torch.float32, device=x.device)
|
| 440 |
if dropout_p > 0.0:
|
| 441 |
seeds = torch.randint(
|
|
|
|
| 503 |
|
| 504 |
@triton.autotune(
|
| 505 |
configs=triton_autotune_configs(),
|
| 506 |
+
key=[
|
| 507 |
+
"N",
|
| 508 |
+
"HAS_DRESIDUAL",
|
| 509 |
+
"STORE_DRESIDUAL",
|
| 510 |
+
"IS_RMS_NORM",
|
| 511 |
+
"HAS_BIAS",
|
| 512 |
+
"HAS_DROPOUT",
|
| 513 |
+
],
|
| 514 |
)
|
| 515 |
# torch compile doesn't like triton.heuristics, so we set these manually when calling the kernel
|
| 516 |
# @triton.heuristics({"HAS_BIAS": lambda args: args["B"] is not None})
|
|
|
|
| 644 |
if HAS_DX1:
|
| 645 |
if HAS_DROPOUT:
|
| 646 |
keep_mask = (
|
| 647 |
+
tl.rand(tl.load(SEEDS + M + row).to(tl.uint32), cols, n_rounds=7)
|
| 648 |
+
> dropout_p
|
| 649 |
)
|
| 650 |
dx1 = tl.where(keep_mask, dx / (1.0 - dropout_p), 0.0)
|
| 651 |
else:
|
| 652 |
dx1 = dx
|
| 653 |
tl.store(DX1 + cols, dx1, mask=mask)
|
| 654 |
if HAS_DROPOUT:
|
| 655 |
+
keep_mask = (
|
| 656 |
+
tl.rand(tl.load(SEEDS + row).to(tl.uint32), cols, n_rounds=7)
|
| 657 |
+
> dropout_p
|
| 658 |
+
)
|
| 659 |
dx = tl.where(keep_mask, dx / (1.0 - dropout_p), 0.0)
|
| 660 |
if HAS_ROWSCALE:
|
| 661 |
rowscale = tl.load(ROWSCALE + row).to(tl.float32)
|
|
|
|
| 738 |
return dx, dw, db, dresidual_in, dx1, dw1, db1, y
|
| 739 |
|
| 740 |
|
| 741 |
+
@triton_op(
|
| 742 |
+
add_op_namespace_prefix("layer_norm_bwd_impl"),
|
| 743 |
+
mutates_args={},
|
| 744 |
+
schema="(Tensor dy, Tensor x, Tensor weight, Tensor bias, float eps, Tensor mean, Tensor rstd, Tensor? dresidual, Tensor? dy1, Tensor? weight1, Tensor? bias1, Tensor? seeds, float dropout_p, Tensor? rowscale, bool has_residual, bool has_x1, bool zero_centered_weight, bool is_rms_norm, ScalarType? x_dtype, bool recompute_output) -> (Tensor dx, Tensor dw, Tensor db, Tensor dresidual_in, Tensor dx1, Tensor dw1, Tensor db1, Tensor y)",
|
| 745 |
+
allow_decomposition=False, # Don't let torch.compile trace inside
|
| 746 |
+
)
|
| 747 |
def _layer_norm_bwd_impl(
|
| 748 |
dy: Tensor,
|
| 749 |
x: Tensor,
|
|
|
|
| 810 |
else None
|
| 811 |
)
|
| 812 |
dx1 = torch.empty_like(dx) if (has_x1 and dropout_p > 0.0) else None
|
| 813 |
+
y = (
|
| 814 |
+
torch.empty(M, N, dtype=dy.dtype, device=dy.device)
|
| 815 |
+
if recompute_output
|
| 816 |
+
else None
|
| 817 |
+
)
|
| 818 |
if recompute_output:
|
| 819 |
+
assert weight1 is None, (
|
| 820 |
+
"recompute_output is not supported with parallel LayerNorm"
|
| 821 |
+
)
|
| 822 |
|
| 823 |
# Less than 64KB per feature: enqueue fused kernel
|
| 824 |
MAX_FUSED_SIZE = 65536 // x.element_size()
|
|
|
|
| 895 |
|
| 896 |
|
| 897 |
class LayerNormFn(torch.autograd.Function):
|
|
|
|
| 898 |
@staticmethod
|
| 899 |
def forward(
|
| 900 |
ctx,
|
|
|
|
| 915 |
return_dropout_mask=False,
|
| 916 |
out_dtype=None,
|
| 917 |
out=None,
|
| 918 |
+
residual_out=None,
|
| 919 |
):
|
| 920 |
x_shape_og = x.shape
|
| 921 |
# reshape input data into 2D tensor
|
| 922 |
x = maybe_contiguous_lastdim(x.reshape(-1, x.shape[-1]))
|
| 923 |
if residual is not None:
|
| 924 |
assert residual.shape == x_shape_og
|
| 925 |
+
residual = maybe_contiguous_lastdim(
|
| 926 |
+
residual.reshape(-1, residual.shape[-1])
|
| 927 |
+
)
|
| 928 |
if x1 is not None:
|
| 929 |
assert x1.shape == x_shape_og
|
| 930 |
assert rowscale is None, "rowscale is not supported with parallel LayerNorm"
|
|
|
|
| 944 |
out = out.reshape(-1, out.shape[-1])
|
| 945 |
if residual_out is not None:
|
| 946 |
residual_out = residual_out.reshape(-1, residual_out.shape[-1])
|
| 947 |
+
y, y1, mean, rstd, residual_out, seeds, dropout_mask, dropout_mask1 = (
|
| 948 |
+
_layer_norm_fwd(
|
| 949 |
+
x,
|
| 950 |
+
weight,
|
| 951 |
+
bias,
|
| 952 |
+
eps,
|
| 953 |
+
residual,
|
| 954 |
+
x1,
|
| 955 |
+
weight1,
|
| 956 |
+
bias1,
|
| 957 |
+
dropout_p=dropout_p,
|
| 958 |
+
rowscale=rowscale,
|
| 959 |
+
out_dtype=out_dtype,
|
| 960 |
+
residual_dtype=residual_dtype,
|
| 961 |
+
zero_centered_weight=zero_centered_weight,
|
| 962 |
+
is_rms_norm=is_rms_norm,
|
| 963 |
+
return_dropout_mask=return_dropout_mask,
|
| 964 |
+
out=out,
|
| 965 |
+
residual_out=residual_out,
|
| 966 |
+
)
|
| 967 |
)
|
| 968 |
ctx.save_for_backward(
|
| 969 |
residual_out, weight, bias, weight1, bias1, rowscale, seeds, mean, rstd
|
|
|
|
| 979 |
ctx.zero_centered_weight = zero_centered_weight
|
| 980 |
y = y.reshape(x_shape_og)
|
| 981 |
y1 = y1.reshape(x_shape_og) if y1 is not None else None
|
| 982 |
+
residual_out = (
|
| 983 |
+
residual_out.reshape(x_shape_og) if residual_out is not None else None
|
| 984 |
+
)
|
| 985 |
+
dropout_mask = (
|
| 986 |
+
dropout_mask.reshape(x_shape_og) if dropout_mask is not None else None
|
| 987 |
+
)
|
| 988 |
+
dropout_mask1 = (
|
| 989 |
+
dropout_mask1.reshape(x_shape_og) if dropout_mask1 is not None else None
|
| 990 |
+
)
|
| 991 |
if not return_dropout_mask:
|
| 992 |
if weight1 is None:
|
| 993 |
return y if not prenorm else (y, residual_out)
|
|
|
|
| 1085 |
return_dropout_mask=False,
|
| 1086 |
out_dtype=None,
|
| 1087 |
out=None,
|
| 1088 |
+
residual_out=None,
|
| 1089 |
):
|
| 1090 |
return LayerNormFn.apply(
|
| 1091 |
x,
|
|
|
|
| 1105 |
return_dropout_mask,
|
| 1106 |
out_dtype,
|
| 1107 |
out,
|
| 1108 |
+
residual_out,
|
| 1109 |
)
|
| 1110 |
|
| 1111 |
|
|
|
|
| 1126 |
return_dropout_mask=False,
|
| 1127 |
out_dtype=None,
|
| 1128 |
out=None,
|
| 1129 |
+
residual_out=None,
|
| 1130 |
):
|
| 1131 |
return LayerNormFn.apply(
|
| 1132 |
x,
|
|
|
|
| 1146 |
return_dropout_mask,
|
| 1147 |
out_dtype,
|
| 1148 |
out,
|
| 1149 |
+
residual_out,
|
| 1150 |
)
|
| 1151 |
|
| 1152 |
|
| 1153 |
class RMSNorm(torch.nn.Module):
|
| 1154 |
+
def __init__(
|
| 1155 |
+
self,
|
| 1156 |
+
hidden_size,
|
| 1157 |
+
eps=1e-5,
|
| 1158 |
+
dropout_p=0.0,
|
| 1159 |
+
zero_centered_weight=False,
|
| 1160 |
+
device=None,
|
| 1161 |
+
dtype=None,
|
| 1162 |
+
):
|
| 1163 |
factory_kwargs = {"device": device, "dtype": dtype}
|
| 1164 |
super().__init__()
|
| 1165 |
self.eps = eps
|
|
|
|
| 1193 |
|
| 1194 |
|
| 1195 |
class LayerNormLinearFn(torch.autograd.Function):
|
|
|
|
| 1196 |
@staticmethod
|
| 1197 |
@custom_fwd
|
| 1198 |
def forward(
|
|
|
|
| 1213 |
x = maybe_contiguous_lastdim(x.reshape(-1, x.shape[-1]))
|
| 1214 |
if residual is not None:
|
| 1215 |
assert residual.shape == x_shape_og
|
| 1216 |
+
residual = maybe_contiguous_lastdim(
|
| 1217 |
+
residual.reshape(-1, residual.shape[-1])
|
| 1218 |
+
)
|
| 1219 |
norm_weight = norm_weight.contiguous()
|
| 1220 |
norm_bias = maybe_contiguous(norm_bias)
|
| 1221 |
residual_dtype = (
|
|
|
|
| 1229 |
norm_bias,
|
| 1230 |
eps,
|
| 1231 |
residual,
|
| 1232 |
+
out_dtype=None
|
| 1233 |
+
if not torch.is_autocast_enabled()
|
| 1234 |
+
else torch.get_autocast_dtype("cuda"),
|
| 1235 |
residual_dtype=residual_dtype,
|
| 1236 |
is_rms_norm=is_rms_norm,
|
| 1237 |
)
|
| 1238 |
y = y.reshape(x_shape_og)
|
| 1239 |
+
dtype = (
|
| 1240 |
+
torch.get_autocast_dtype("cuda") if torch.is_autocast_enabled() else y.dtype
|
| 1241 |
+
)
|
| 1242 |
linear_weight = linear_weight.to(dtype)
|
| 1243 |
linear_bias = linear_bias.to(dtype) if linear_bias is not None else None
|
| 1244 |
out = F.linear(y.to(linear_weight.dtype), linear_weight, linear_bias)
|
| 1245 |
# We don't store y, will be recomputed in the backward pass to save memory
|
| 1246 |
+
ctx.save_for_backward(
|
| 1247 |
+
residual_out, norm_weight, norm_bias, linear_weight, mean, rstd
|
| 1248 |
+
)
|
| 1249 |
ctx.x_shape_og = x_shape_og
|
| 1250 |
ctx.eps = eps
|
| 1251 |
ctx.is_rms_norm = is_rms_norm
|
|
|
|
| 1266 |
assert dy.shape == x.shape
|
| 1267 |
if ctx.prenorm:
|
| 1268 |
dresidual = args[0]
|
| 1269 |
+
dresidual = maybe_contiguous_lastdim(
|
| 1270 |
+
dresidual.reshape(-1, dresidual.shape[-1])
|
| 1271 |
+
)
|
| 1272 |
else:
|
| 1273 |
dresidual = None
|
| 1274 |
dx, dnorm_weight, dnorm_bias, dresidual_in, _, _, _, y = _layer_norm_bwd(
|
build/torch-cuda/metadata.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
| 1 |
{
|
| 2 |
"name": "flash-attn-ops",
|
| 3 |
-
"id": "
|
| 4 |
"version": 1,
|
| 5 |
"license": "BSD-3-Clause",
|
| 6 |
"python-depends": [],
|
|
@@ -11,17 +11,27 @@
|
|
| 11 |
"algorithm": "sha256",
|
| 12 |
"files": {
|
| 13 |
"__init__.py": "CN2UymE7gbYnzhbAm92qHBHVC/as55EjJsW+EQt5eaM=",
|
| 14 |
-
"_ops.py": "
|
| 15 |
-
"_ops_compat.py": "xs6BjkzWExaqXt9xniN5UNYqTp0kpEehRyOyx16+a5o=",
|
| 16 |
"cross_entropy.py": "y56nmuOtpSNxM7sDZcUSgXKIsIEayfuvrU8bAVog/nw=",
|
| 17 |
"flash_attn_ops/__init__.py": "DFYPlrhXwYjEqCl/8n0SmWGZV8NFml5DPhMjKfv98GY=",
|
| 18 |
"k_activations.py": "+Z3vIyO4JkqBMipKsPvhzmxljtBdIhJCsl/M+/ESqBo=",
|
| 19 |
-
"layer_norm.py": "
|
| 20 |
"losses.py": "YhTM9q3Qouq8QoFy1hryAXFC2A6scVtnReoNa+l99YQ=",
|
| 21 |
"rotary.py": "0gN+YjhUxwL7B1eE/kKS1Kida5rBrjPKs9Z4j4+U8kA=",
|
| 22 |
"utils/__init__.py": "47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=",
|
| 23 |
"utils/library.py": "nKTJmAHNSqc30g95/NPDtvqzP4GWgYN0BNh015AFzYM=",
|
| 24 |
"utils/torch.py": "7mVlWFrCGE7XuCLO9oHa5Z8c4HPLYnE0ojYOJHh8JiQ="
|
| 25 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 26 |
}
|
| 27 |
}
|
|
|
|
| 1 |
{
|
| 2 |
"name": "flash-attn-ops",
|
| 3 |
+
"id": "_flash_attn_ops_cuda_8a730d9",
|
| 4 |
"version": 1,
|
| 5 |
"license": "BSD-3-Clause",
|
| 6 |
"python-depends": [],
|
|
|
|
| 11 |
"algorithm": "sha256",
|
| 12 |
"files": {
|
| 13 |
"__init__.py": "CN2UymE7gbYnzhbAm92qHBHVC/as55EjJsW+EQt5eaM=",
|
| 14 |
+
"_ops.py": "qQNowLEFyFPzxnfTsNt9k+zqYB65oQJozdV6LFvAvNQ=",
|
|
|
|
| 15 |
"cross_entropy.py": "y56nmuOtpSNxM7sDZcUSgXKIsIEayfuvrU8bAVog/nw=",
|
| 16 |
"flash_attn_ops/__init__.py": "DFYPlrhXwYjEqCl/8n0SmWGZV8NFml5DPhMjKfv98GY=",
|
| 17 |
"k_activations.py": "+Z3vIyO4JkqBMipKsPvhzmxljtBdIhJCsl/M+/ESqBo=",
|
| 18 |
+
"layer_norm.py": "SVUTedaQF7zdKwg4bNnr8NPWFSUPB+88kSLWyPkykh0=",
|
| 19 |
"losses.py": "YhTM9q3Qouq8QoFy1hryAXFC2A6scVtnReoNa+l99YQ=",
|
| 20 |
"rotary.py": "0gN+YjhUxwL7B1eE/kKS1Kida5rBrjPKs9Z4j4+U8kA=",
|
| 21 |
"utils/__init__.py": "47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=",
|
| 22 |
"utils/library.py": "nKTJmAHNSqc30g95/NPDtvqzP4GWgYN0BNh015AFzYM=",
|
| 23 |
"utils/torch.py": "7mVlWFrCGE7XuCLO9oHa5Z8c4HPLYnE0ojYOJHh8JiQ="
|
| 24 |
}
|
| 25 |
+
},
|
| 26 |
+
"provenance": {
|
| 27 |
+
"kernel-builder": {
|
| 28 |
+
"version": "0.17.0-dev0",
|
| 29 |
+
"sha": "81580bb92577f2f7228661ca2a221fc052375709",
|
| 30 |
+
"dirty": false
|
| 31 |
+
},
|
| 32 |
+
"kernel": {
|
| 33 |
+
"sha": "8a730d96c37560ccf1d3e09f7bbccdc886818f33",
|
| 34 |
+
"dirty": false
|
| 35 |
+
}
|
| 36 |
}
|
| 37 |
}
|
build/torch-cuda/metadata.json.sigstore
CHANGED
|
@@ -1 +1 @@
|
|
| 1 |
-
{"mediaType":"application/vnd.dev.sigstore.bundle.v0.3+json","verificationMaterial":{"certificate":{"rawBytes":"MIIHSjCCBtGgAwIBAgIUOlUfAEbtfthPfGw7fDjT0prT3ggwCgYIKoZIzj0EAwMwNzEVMBMGA1UEChMMc2lnc3RvcmUuZGV2MR4wHAYDVQQDExVzaWdzdG9yZS1pbnRlcm1lZGlhdGUwHhcNMjYwNzAzMTIwOTIwWhcNMjYwNzAzMTIxOTIwWjAAMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEDNCxS/AgnBrb/HmNFA2g9P+lJyQ76Lr5fcwlUfxIib61DJ0nvqK5q+sC6kzT3aqQQynTqdudxepSUBjndLyYdKOCBfAwggXsMA4GA1UdDwEB/wQEAwIHgDATBgNVHSUEDDAKBggrBgEFBQcDAzAdBgNVHQ4EFgQUK8gDLuPcRgJgapENEF0jUNA8HTowHwYDVR0jBBgwFoAU39Ppz1YkEZb5qNjpKFWixi4YZD8wawYDVR0RAQH/BGEwX4ZdaHR0cHM6Ly9naXRodWIuY29tL2h1Z2dpbmdmYWNlL2tlcm5lbHMtY29tbXVuaXR5Ly5naXRodWIvd29ya2Zsb3dzL2J1aWxkLnlhbWxAcmVmcy9oZWFkcy9tYWluMDkGCisGAQQBg78wAQEEK2h0dHBzOi8vdG9rZW4uYWN0aW9ucy5naXRodWJ1c2VyY29udGVudC5jb20wHwYKKwYBBAGDvzABAgQRd29ya2Zsb3dfZGlzcGF0Y2gwNgYKKwYBBAGDvzABAwQoMmU0Yjk3NjIxZTkzNzk3NDEzMmY1NDNkYjI1MTEyNjgwNmY5NGJiZTATBgorBgEEAYO/MAEEBAVCdWlsZDArBgorBgEEAYO/MAEFBB1odWdnaW5nZmFjZS9rZXJuZWxzLWNvbW11bml0eTAdBgorBgEEAYO/MAEGBA9yZWZzL2hlYWRzL21haW4wOwYKKwYBBAGDvzABCAQtDCtodHRwczovL3Rva2VuLmFjdGlvbnMuZ2l0aHVidXNlcmNvbnRlbnQuY29tMG0GCisGAQQBg78wAQkEXwxdaHR0cHM6Ly9naXRodWIuY29tL2h1Z2dpbmdmYWNlL2tlcm5lbHMtY29tbXVuaXR5Ly5naXRodWIvd29ya2Zsb3dzL2J1aWxkLnlhbWxAcmVmcy9oZWFkcy9tYWluMDgGCisGAQQBg78wAQoEKgwoMmU0Yjk3NjIxZTkzNzk3NDEzMmY1NDNkYjI1MTEyNjgwNmY5NGJiZTAbBgorBgEEAYO/MAELBA0MC3NlbGYtaG9zdGVkMEAGCisGAQQBg78wAQwEMgwwaHR0cHM6Ly9naXRodWIuY29tL2h1Z2dpbmdmYWNlL2tlcm5lbHMtY29tbXVuaXR5MDgGCisGAQQBg78wAQ0EKgwoMmU0Yjk3NjIxZTkzNzk3NDEzMmY1NDNkYjI1MTEyNjgwNmY5NGJiZTAfBgorBgEEAYO/MAEOBBEMD3JlZnMvaGVhZHMvbWFpbjAaBgorBgEEAYO/MAEPBAwMCjEwNzE0NzU1MjkwLgYKKwYBBAGDvzABEAQgDB5odHRwczovL2dpdGh1Yi5jb20vaHVnZ2luZ2ZhY2UwGAYKKwYBBAGDvzABEQQKDAgyNTcyMDc0MzBtBgorBgEEAYO/MAESBF8MXWh0dHBzOi8vZ2l0aHViLmNvbS9odWdnaW5nZmFjZS9rZXJuZWxzLWNvbW11bml0eS8uZ2l0aHViL3dvcmtmbG93cy9idWlsZC55YW1sQHJlZnMvaGVhZHMvbWFpbjA4BgorBgEEAYO/MAETBCoMKDJlNGI5NzYyMWU5Mzc5NzQxMzJmNTQzZGIyNTExMjY4MDZmOTRiYmUwIQYKKwYBBAGDvzABFAQTDBF3b3JrZmxvd19kaXNwYXRjaDBkBgorBgEEAYO/MAEVBFYMVGh0dHBzOi8vZ2l0aHViLmNvbS9odWdnaW5nZmFjZS9rZXJuZWxzLWNvbW11bml0eS9hY3Rpb25zL3J1bnMvMjg2NTg3NTI1MjgvYXR0ZW1wdHMvMTAWBgorBgEEAYO/MAEWBAgMBnB1YmxpYzBGBgorBgEEAYO/MAEYBDgMNnJlcG86aHVnZ2luZ2ZhY2Uva2VybmVscy1jb21tdW5pdHk6cmVmOnJlZnMvaGVhZHMvbWFpbjCBigYKKwYBBAHWeQIEAgR8BHoAeAB2AN09MGrGxxEyYxkeHJlnNwKiSl643jyt/4eKcoAvKe6OAAABnyfiJ5kAAAQDAEcwRQIhANYsKKhwp+jokEG5vWjGgq5Oh0vvovZUd4v2NTT0Wp8WAiBT2YYP+qUfzbHOSI+kOSK8SAFfxrsBuW+9Ny46bCCVAzAKBggqhkjOPQQDAwNnADBkAjASMs+EqJ047/Sw5kd4QT2KFXmJQW9tISAxHvVzUf32uoPWrUyyXztMbTJ4Um6xFKgCMD0+nKl0puOYII6qZOHF5DtmxT6Rjrm0zvh5dMr9ddmrl8WZu1EwKIv0MWBuz3mh0g=="},"tlogEntries":[{"logIndex":"2060197916","logId":{"keyId":"wNI9atQGlz+VWfO6LRygH4QUfY/8W4RFwiT5i5WRgB0="},"kindVersion":{"kind":"hashedrekord","version":"0.0.1"},"integratedTime":"1783080561","inclusionPromise":{"signedEntryTimestamp":"MEUCIFrMGIfLhIxLhETxbQ5OfS52T2txLjLdRB8KjTLlODP7AiEAmiPJPKmgyB1/6lv1AaoE+KjykwCJlIrzI0RkDXEc3pc="},"inclusionProof":{"logIndex":"1938293654","rootHash":"gPz2NSUbLz8lIu3LXY9jfQ07DCa5oaOCDWfdLs4tUR8=","treeSize":"1938293730","hashes":["yJha0KKb0usEfZVMpgK6L/B2iAfLVcOksOwrd78VBSU=","+PU3zRAgU24fymk+h38rChHkLnDtSzRexLdLY562loM=","cwtotohNjqIzjkd69PJo95wBbfcVf7JxVFH2xRjaHk8=","dduNWHkPBB7HIn27N/cE/BeBwVyddRaKkOU7z/H684I=","Bz1UNJYdYVUVyd44dg6GziUUnaWQjiDduEH5H3Xc5UQ=","MqGmWuECTxAuHDgw/dWSvGFP+9rG4p1YGKqwfgrY2xQ=","4605als7RalrKpwjXwzLJTrIVGGZe2sDnGmN4LWkUaM=","2O0Ku6E3Gs7WqZeylo/Q1khiKlgJeUpYTIIil+KxG10=","0YjjV5PnMTeytImbzyW9/jPX6jnOolVeuXHyRfr4yng=","b5cJfno78yVRVpk9SUvKzNVf5K8QDlfznvCcHs9Auus=","7t7nfpRXFFwOWiZ7hqJrJVEhGZwD31UptO0/dy5iWfI=","RIZjwQJv61lwM5JOP8iNT/RxKPr522/etVqxVBWn7KA=","b69YlhA5qlDwN70us4bq9ysnikE1ulA7EwKBTb+atY0=","LM7F5iwbk8jG29X4FwpkCN6BqDCfuNQTlz5CyQWt87s=","+/VZ56MsIPxMiyLAodzKXo5TEWdQp36z89qLhpzloAo=","daxmZaajRpZV+JxHiOYZhJBiSKN5ucqjh2WnGbHhirw=","DOCeoSMovIvLExkhIvisow9AuNXgeWs4ECkyR6EcqYU="],"checkpoint":{"envelope":"rekor.sigstore.dev - 1193050959916656506\n1938293730\ngPz2NSUbLz8lIu3LXY9jfQ07DCa5oaOCDWfdLs4tUR8=\n\n— rekor.sigstore.dev wNI9ajBFAiAzxny9hSItHnCfVkjrF3tB/HaBYDjqUnDn4B9XqDGTtgIhALJIFKr8NsGzLXVHS1OVRwdhUNXSkkTkosfA1AH7Gv6E\n"}},"canonicalizedBody":"eyJhcGlWZXJzaW9uIjoiMC4wLjEiLCJraW5kIjoiaGFzaGVkcmVrb3JkIiwic3BlYyI6eyJkYXRhIjp7Imhhc2giOnsiYWxnb3JpdGhtIjoic2hhMjU2IiwidmFsdWUiOiI2ZGE3Yzg0NmExOTc0M2Q5NDEzYTRmMmNlOGRlYjBiMjM3Y2EzNWQ1MWZkY2U2ZTZkNmQ3YmZjMzdmMDNiNDZhIn19LCJzaWduYXR1cmUiOnsiY29udGVudCI6Ik1FVUNJRFByNmZHVjNaalpxc3lhMUZRTUxFV1BEZHN6Wm5rTk5tYUFwMWtOUGQwbUFpRUEvbC9id0d2ejB4V0VCTDVUcVBnL1h6eXJCWVFzUGZuYUNnL1FyM0tvWVdJPSIsInB1YmxpY0tleSI6eyJjb250ZW50IjoiTFMwdExTMUNSVWRKVGlCRFJWSlVTVVpKUTBGVVJTMHRMUzB0Q2sxSlNVaFRha05EUW5SSFowRjNTVUpCWjBsVlQyeFZaa0ZGWW5SbWRHaFFaa2QzTjJaRWFsUXdjSEpVTTJkbmQwTm5XVWxMYjFwSmVtb3dSVUYzVFhjS1RucEZWazFDVFVkQk1WVkZRMmhOVFdNeWJHNWpNMUoyWTIxVmRWcEhWakpOVWpSM1NFRlpSRlpSVVVSRmVGWjZZVmRrZW1SSE9YbGFVekZ3WW01U2JBcGpiVEZzV2tkc2FHUkhWWGRJYUdOT1RXcFpkMDU2UVhwTlZFbDNUMVJKZDFkb1kwNU5hbGwzVG5wQmVrMVVTWGhQVkVsM1YycEJRVTFHYTNkRmQxbElDa3R2V2tsNmFqQkRRVkZaU1V0dldrbDZhakJFUVZGalJGRm5RVVZFVGtONFV5OUJaMjVDY21JdlNHMU9Sa0V5WnpsUUsyeEtlVkUzTmt4eU5XWmpkMndLVldaNFNXbGlOakZFU2pCdWRuRkxOWEVyYzBNMmEzcFVNMkZ4VVZGNWJsUnhaSFZrZUdWd1UxVkNhbTVrVEhsWlpFdFBRMEptUVhkbloxaHpUVUUwUndwQk1WVmtSSGRGUWk5M1VVVkJkMGxJWjBSQlZFSm5UbFpJVTFWRlJFUkJTMEpuWjNKQ1owVkdRbEZqUkVGNlFXUkNaMDVXU0ZFMFJVWm5VVlZMT0dkRUNreDFVR05TWjBwbllYQkZUa1ZHTUdwVlRrRTRTRlJ2ZDBoM1dVUldVakJxUWtKbmQwWnZRVlV6T1ZCd2VqRlphMFZhWWpWeFRtcHdTMFpYYVhocE5Ga0tXa1E0ZDJGM1dVUldVakJTUVZGSUwwSkhSWGRZTkZwa1lVaFNNR05JVFRaTWVUbHVZVmhTYjJSWFNYVlpNamwwVERKb01Wb3laSEJpYldSdFdWZE9iQXBNTW5Sc1kyMDFiR0pJVFhSWk1qbDBZbGhXZFdGWVVqVk1lVFZ1WVZoU2IyUlhTWFprTWpsNVlUSmFjMkl6WkhwTU1rb3hZVmQ0YTB4dWJHaGlWM2hCQ21OdFZtMWplVGx2V2xkR2EyTjVPWFJaVjJ4MVRVUnJSME5wYzBkQlVWRkNaemM0ZDBGUlJVVkxNbWd3WkVoQ2VrOXBPSFprUnpseVdsYzBkVmxYVGpBS1lWYzVkV041Tlc1aFdGSnZaRmRLTVdNeVZubFpNamwxWkVkV2RXUkROV3BpTWpCM1NIZFpTMHQzV1VKQ1FVZEVkbnBCUWtGblVWSmtNamw1WVRKYWN3cGlNMlJtV2tkc2VtTkhSakJaTW1kM1RtZFpTMHQzV1VKQ1FVZEVkbnBCUWtGM1VXOU5iVlV3V1dwck0wNXFTWGhhVkd0NlRucHJNMDVFUlhwTmJWa3hDazVFVG10WmFra3hUVlJGZVU1cVozZE9iVmsxVGtkS2FWcFVRVlJDWjI5eVFtZEZSVUZaVHk5TlFVVkZRa0ZXUTJSWGJITmFSRUZ5UW1kdmNrSm5SVVVLUVZsUEwwMUJSVVpDUWpGdlpGZGtibUZYTlc1YWJVWnFXbE01Y2xwWVNuVmFWM2g2VEZkT2RtSlhNVEZpYld3d1pWUkJaRUpuYjNKQ1owVkZRVmxQTHdwTlFVVkhRa0U1ZVZwWFducE1NbWhzV1ZkU2Vrd3lNV2hoVnpSM1QzZFpTMHQzV1VKQ1FVZEVkbnBCUWtOQlVYUkVRM1J2WkVoU2QyTjZiM1pNTTFKMkNtRXlWblZNYlVacVpFZHNkbUp1VFhWYU1td3dZVWhXYVdSWVRteGpiVTUyWW01U2JHSnVVWFZaTWpsMFRVY3dSME5wYzBkQlVWRkNaemM0ZDBGUmEwVUtXSGQ0WkdGSVVqQmpTRTAyVEhrNWJtRllVbTlrVjBsMVdUSTVkRXd5YURGYU1tUndZbTFrYlZsWFRteE1NblJzWTIwMWJHSklUWFJaTWpsMFlsaFdkUXBoV0ZJMVRIazFibUZZVW05a1YwbDJaREk1ZVdFeVduTmlNMlI2VERKS01XRlhlR3RNYm14b1lsZDRRV050Vm0xamVUbHZXbGRHYTJONU9YUlpWMngxQ2sxRVowZERhWE5IUVZGUlFtYzNPSGRCVVc5RlMyZDNiMDF0VlRCWmFtc3pUbXBKZUZwVWEzcE9lbXN6VGtSRmVrMXRXVEZPUkU1cldXcEpNVTFVUlhrS1RtcG5kMDV0V1RWT1IwcHBXbFJCWWtKbmIzSkNaMFZGUVZsUEwwMUJSVXhDUVRCTlF6Tk9iR0pIV1hSaFJ6bDZaRWRXYTAxRlFVZERhWE5IUVZGUlFncG5OemgzUVZGM1JVMW5kM2RoU0ZJd1kwaE5Oa3g1T1c1aFdGSnZaRmRKZFZreU9YUk1NbWd4V2pKa2NHSnRaRzFaVjA1c1RESjBiR050Tld4aVNFMTBDbGt5T1hSaVdGWjFZVmhTTlUxRVowZERhWE5IUVZGUlFtYzNPSGRCVVRCRlMyZDNiMDF0VlRCWmFtc3pUbXBKZUZwVWEzcE9lbXN6VGtSRmVrMXRXVEVLVGtST2ExbHFTVEZOVkVWNVRtcG5kMDV0V1RWT1IwcHBXbFJCWmtKbmIzSkNaMFZGUVZsUEwwMUJSVTlDUWtWTlJETktiRnB1VFhaaFIxWm9Xa2hOZGdwaVYwWndZbXBCWVVKbmIzSkNaMFZGUVZsUEwwMUJSVkJDUVhkTlEycEZkMDU2UlRCT2VsVXhUV3ByZDB4bldVdExkMWxDUWtGSFJIWjZRVUpGUVZGbkNrUkNOVzlrU0ZKM1kzcHZka3d5WkhCa1IyZ3hXV2sxYW1JeU1IWmhTRlp1V2pKc2RWb3lXbWhaTWxWM1IwRlpTMHQzV1VKQ1FVZEVkbnBCUWtWUlVVc0tSRUZuZVU1VVkzbE5SR013VFhwQ2RFSm5iM0pDWjBWRlFWbFBMMDFCUlZOQ1JqaE5XRmRvTUdSSVFucFBhVGgyV2pKc01HRklWbWxNYlU1MllsTTVid3BrVjJSdVlWYzFibHB0Um1wYVV6bHlXbGhLZFZwWGVIcE1WMDUyWWxjeE1XSnRiREJsVXpoMVdqSnNNR0ZJVm1sTU0yUjJZMjEwYldKSE9UTmplVGxwQ21SWGJITmFRelUxV1ZjeGMxRklTbXhhYmsxMllVZFdhRnBJVFhaaVYwWndZbXBCTkVKbmIzSkNaMFZGUVZsUEwwMUJSVlJDUTI5TlMwUktiRTVIU1RVS1RucFplVTFYVlRWTmVtTTFUbnBSZUUxNlNtMU9WRkY2V2tkSmVVNVVSWGhOYWxrMFRVUmFiVTlVVW1sWmJWVjNTVkZaUzB0M1dVSkNRVWRFZG5wQlFncEdRVkZVUkVKR00ySXpTbkphYlhoMlpERTVhMkZZVG5kWldGSnFZVVJDYTBKbmIzSkNaMFZGUVZsUEwwMUJSVlpDUmxsTlZrZG9NR1JJUW5wUGFUaDJDbG95YkRCaFNGWnBURzFPZG1KVE9XOWtWMlJ1WVZjMWJscHRSbXBhVXpseVdsaEtkVnBYZUhwTVYwNTJZbGN4TVdKdGJEQmxVemxvV1ROU2NHSXlOWG9LVEROS01XSnVUWFpOYW1jeVRsUm5NMDVVU1RGTmFtZDJXVmhTTUZwWE1YZGtTRTEyVFZSQlYwSm5iM0pDWjBWRlFWbFBMMDFCUlZkQ1FXZE5RbTVDTVFwWmJYaHdXWHBDUjBKbmIzSkNaMFZGUVZsUEwwMUJSVmxDUkdkTlRtNUtiR05IT0RaaFNGWnVXakpzZFZveVdtaFpNbFYyWVRKV2VXSnRWbk5qZVRGcUNtSXlNWFJrVnpWd1pFaHJObU50Vm0xUGJrcHNXbTVOZG1GSFZtaGFTRTEyWWxkR2NHSnFRMEpwWjFsTFMzZFpRa0pCU0ZkbFVVbEZRV2RTT0VKSWIwRUtaVUZDTWtGT01EbE5SM0pIZUhoRmVWbDRhMlZJU214dVRuZExhVk5zTmpRemFubDBMelJsUzJOdlFYWkxaVFpQUVVGQlFtNTVabWxLTld0QlFVRlJSQXBCUldOM1VsRkphRUZPV1hOTFMyaDNjQ3RxYjJ0RlJ6VjJWMnBIWjNFMVQyZ3dkblp2ZGxwVlpEUjJNazVVVkRCWGNEaFhRV2xDVkRKWldWQXJjVlZtQ25waVNFOVRTU3RyVDFOTE9GTkJSbVo0Y25OQ2RWY3JPVTU1TkRaaVEwTldRWHBCUzBKblozRm9hMnBQVUZGUlJFRjNUbTVCUkVKclFXcEJVMDF6SzBVS2NVb3dORGN2VTNjMWEyUTBVVlF5UzBaWWJVcFJWemwwU1ZOQmVFaDJWbnBWWmpNeWRXOVFWM0pWZVhsWWVuUk5ZbFJLTkZWdE5uaEdTMmREVFVRd0t3cHVTMnd3Y0hWUFdVbEpObkZhVDBoR05VUjBiWGhVTmxKcWNtMHdlblpvTldSTmNqbGtaRzF5YkRoWFduVXhSWGRMU1hZd1RWZENkWG96Yldnd1p6MDlDaTB0TFMwdFJVNUVJRU5GVWxSSlJrbERRVlJGTFMwdExTMEsifX19fQ=="}],"timestampVerificationData":{"rfc3161Timestamps":[{"signedTimestamp":"MIICyjADAgEAMIICwQYJKoZIhvcNAQcCoIICsjCCAq4CAQMxDTALBglghkgBZQMEAgEwgbgGCyqGSIb3DQEJEAEEoIGoBIGlMIGiAgEBBgkrBgEEAYO/MAIwMTANBglghkgBZQMEAgEFAAQgpjGhppJpk24JdlqEoOPEMsgq+wu9YtJVgdGkOuzyqCICFQCpu8lcYrDDQ12zZZQFZh5Lpez2pRgPMjAyNjA3MDMxMjA5MjBaMAMCAQGgMqQwMC4xFTATBgNVBAoTDHNpZ3N0b3JlLmRldjEVMBMGA1UEAxMMc2lnc3RvcmUtdHNhoAAxggHbMIIB1wIBATBRMDkxFTATBgNVBAoTDHNpZ3N0b3JlLmRldjEgMB4GA1UEAxMXc2lnc3RvcmUtdHNhLXNlbGZzaWduZWQCFDoTVC8MkGHuvMFDL8uKjosqI4sMMAsGCWCGSAFlAwQCAaCB/DAaBgkqhkiG9w0BCQMxDQYLKoZIhvcNAQkQAQQwHAYJKoZIhvcNAQkFMQ8XDTI2MDcwMzEyMDkyMFowLwYJKoZIhvcNAQkEMSIEIHJsNCxDogcjsHrvO50oiTqDvFnaUMtf+LwpYUyV6aUXMIGOBgsqhkiG9w0BCRACLzF/MH0wezB5BCCF+Se8B6tiysO0Q1bBDvyBssaIP9p6uebYcNnROs0FtzBVMD2kOzA5MRUwEwYDVQQKEwxzaWdzdG9yZS5kZXYxIDAeBgNVBAMTF3NpZ3N0b3JlLXRzYS1zZWxmc2lnbmVkAhQ6E1QvDJBh7rzBQy/Lio6LKiOLDDAKBggqhkjOPQQDAgRnMGUCMQDxiFyZHI5+D6bpr9Z7MAiV2vUJ1kJGe5xD4L1SYMm5zG/ywAE1+S2HaWKrQ9otVzYCMFgroTZmzztiLFGlqkKgAbMCckD1i1AP937uB4trvAEAQE+Xf5kW4xUCuPO6RpE1jg=="}]}},"messageSignature":{"messageDigest":{"algorithm":"SHA2_256","digest":"bafIRqGXQ9lBOk8s6N6wsjfKNdUf3Obm1te/w38DtGo="},"signature":"MEUCIDPr6fGV3ZjZqsya1FQMLEWPDdszZnkNNmaAp1kNPd0mAiEA/l/bwGvz0xWEBL5TqPg/XzyrBYQsPfnaCg/Qr3KoYWI="}}
|
|
|
|
| 1 |
+
{"mediaType":"application/vnd.dev.sigstore.bundle.v0.3+json", "verificationMaterial":{"certificate":{"rawBytes":"MIIHSzCCBtGgAwIBAgIUEE03co9plfqEjv6C6fBMqQMVscUwCgYIKoZIzj0EAwMwNzEVMBMGA1UEChMMc2lnc3RvcmUuZGV2MR4wHAYDVQQDExVzaWdzdG9yZS1pbnRlcm1lZGlhdGUwHhcNMjYwNzA4MDkzNjEwWhcNMjYwNzA4MDk0NjEwWjAAMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAErXjaDQ6jAg8TSmfpxGnfDbVzV/4Azr1dZRyC9GQGLohqps2ORsMPHzcJ9ddq20aVebDB+ahbgzFBgVFjmU7GnqOCBfAwggXsMA4GA1UdDwEB/wQEAwIHgDATBgNVHSUEDDAKBggrBgEFBQcDAzAdBgNVHQ4EFgQUQVQu3XRHLv1kLfF81/mJl6UT9yswHwYDVR0jBBgwFoAU39Ppz1YkEZb5qNjpKFWixi4YZD8wawYDVR0RAQH/BGEwX4ZdaHR0cHM6Ly9naXRodWIuY29tL2h1Z2dpbmdmYWNlL2tlcm5lbHMtY29tbXVuaXR5Ly5naXRodWIvd29ya2Zsb3dzL2J1aWxkLnlhbWxAcmVmcy9oZWFkcy9tYWluMDkGCisGAQQBg78wAQEEK2h0dHBzOi8vdG9rZW4uYWN0aW9ucy5naXRodWJ1c2VyY29udGVudC5jb20wHwYKKwYBBAGDvzABAgQRd29ya2Zsb3dfZGlzcGF0Y2gwNgYKKwYBBAGDvzABAwQoOGE3MzBkOTZjMzc1NjBjY2YxZDNlMDlmN2JiY2NkYzg4NjgxOGYzMzATBgorBgEEAYO/MAEEBAVCdWlsZDArBgorBgEEAYO/MAEFBB1odWdnaW5nZmFjZS9rZXJuZWxzLWNvbW11bml0eTAdBgorBgEEAYO/MAEGBA9yZWZzL2hlYWRzL21haW4wOwYKKwYBBAGDvzABCAQtDCtodHRwczovL3Rva2VuLmFjdGlvbnMuZ2l0aHVidXNlcmNvbnRlbnQuY29tMG0GCisGAQQBg78wAQkEXwxdaHR0cHM6Ly9naXRodWIuY29tL2h1Z2dpbmdmYWNlL2tlcm5lbHMtY29tbXVuaXR5Ly5naXRodWIvd29ya2Zsb3dzL2J1aWxkLnlhbWxAcmVmcy9oZWFkcy9tYWluMDgGCisGAQQBg78wAQoEKgwoOGE3MzBkOTZjMzc1NjBjY2YxZDNlMDlmN2JiY2NkYzg4NjgxOGYzMzAbBgorBgEEAYO/MAELBA0MC3NlbGYtaG9zdGVkMEAGCisGAQQBg78wAQwEMgwwaHR0cHM6Ly9naXRodWIuY29tL2h1Z2dpbmdmYWNlL2tlcm5lbHMtY29tbXVuaXR5MDgGCisGAQQBg78wAQ0EKgwoOGE3MzBkOTZjMzc1NjBjY2YxZDNlMDlmN2JiY2NkYzg4NjgxOGYzMzAfBgorBgEEAYO/MAEOBBEMD3JlZnMvaGVhZHMvbWFpbjAaBgorBgEEAYO/MAEPBAwMCjEwNzE0NzU1MjkwLgYKKwYBBAGDvzABEAQgDB5odHRwczovL2dpdGh1Yi5jb20vaHVnZ2luZ2ZhY2UwGAYKKwYBBAGDvzABEQQKDAgyNTcyMDc0MzBtBgorBgEEAYO/MAESBF8MXWh0dHBzOi8vZ2l0aHViLmNvbS9odWdnaW5nZmFjZS9rZXJuZWxzLWNvbW11bml0eS8uZ2l0aHViL3dvcmtmbG93cy9idWlsZC55YW1sQHJlZnMvaGVhZHMvbWFpbjA4BgorBgEEAYO/MAETBCoMKDhhNzMwZDk2YzM3NTYwY2NmMWQzZTA5ZjdiYmNjZGM4ODY4MThmMzMwIQYKKwYBBAGDvzABFAQTDBF3b3JrZmxvd19kaXNwYXRjaDBkBgorBgEEAYO/MAEVBFYMVGh0dHBzOi8vZ2l0aHViLmNvbS9odWdnaW5nZmFjZS9rZXJuZWxzLWNvbW11bml0eS9hY3Rpb25zL3J1bnMvMjg5MzEyMDI0MzIvYXR0ZW1wdHMvMTAWBgorBgEEAYO/MAEWBAgMBnB1YmxpYzBGBgorBgEEAYO/MAEYBDgMNnJlcG86aHVnZ2luZ2ZhY2Uva2VybmVscy1jb21tdW5pdHk6cmVmOnJlZnMvaGVhZHMvbWFpbjCBigYKKwYBBAHWeQIEAgR8BHoAeAB2AN09MGrGxxEyYxkeHJlnNwKiSl643jyt/4eKcoAvKe6OAAABn0EVuJ4AAAQDAEcwRQIhAK6jlF9Ixz9e/xTCxVOdECF56DzmbJmN76Z45Hw5ub+oAiBhSJOtm/Ss9XDb0T0t7h8cuppT1ke1JG5s8cN8vepl1DAKBggqhkjOPQQDAwNoADBlAjATX4bvuC4htAHAXmnvOhGu7WJaQvFtAfTTdOsuXIbnO8VwxG0pO4Z98JoIUv3a+wQCMQCL13oHjkbPbe3YZy6BN2dfxHMFp15gwfvKlmZ/ana0Ixji6shwQyi+EodOrjS3zBA="}, "tlogEntries":[{"logIndex":"2114062447", "logId":{"keyId":"wNI9atQGlz+VWfO6LRygH4QUfY/8W4RFwiT5i5WRgB0="}, "kindVersion":{"kind":"hashedrekord", "version":"0.0.1"}, "integratedTime":"1783503370", "inclusionPromise":{"signedEntryTimestamp":"MEQCIGULcIB/P5bOtSQFL7zECviyDrT1v6HYnNcOSisMKTAVAiAtQ1U+e6QIUw4GftXfOnTSSFvoDjEeaRhy6HC7N1MsGA=="}, "inclusionProof":{"logIndex":"1992158185", "rootHash":"sZ2Cpq9sCXL4mLvge3quWz8dvrjoDma3YudecTfnSfw=", "treeSize":"1992158187", "hashes":["4H9wkoPKjmBb47xG+bIY9itX9zri+FT0XvvdnjsQ2WU=", "BCVjCP0q/u1HhNdfwREn/VV3bL/8RfAaOQuu3qBgDEU=", "kQ7fcc9d76EvAexPLiVHzpMUUy6NzxEE2G8ZvickbcE=", "ZPO+n58XzQZtmoo7R9cVwyUw/rf3ZXHxPwoxNI1AKu0=", "C/83T0LtgCGOI9u8toJmdS2iIcOmXIvOx/gudBzyWWw=", "lwsNHEM6qJIqfbQe7ZvedAABUsLMZLDOD1xWJHQH1UU=", "Usxh6EvyE9A1zFrYsjfJHvqZycxmIXNgyzfacgnlE48=", "VdcdobyFjwqP6NbAvWaSE/pTWrRccgdl/PbLqF1kZWk=", "DKfazLC+UbUHA0cM6HRVM99d45RuRYGI6beeOTbtJi4=", "6WLV5MAiMmlAor5VYea+SrvSf5ZMe66flxXztNFFIhk=", "+OMAiJ79sBwk/ZbFDPilfkgmCem1MbCFpLOfIHSetfc=", "tY8nHkJkYkzR0a8crBzP4XX2ys6vaQR/b0ImUbbsFfk=", "W8OH9B7+IUIWw6Asm1BMB4ZxX27Q2QG2hpA1yZ+WxAQ=", "q0bDCYYM8Kl1AcQlFtAjsMRkDgQDRjrR/EhSNDT6HeI=", "Uh9Q3t0owp3nQij7uUVzswxCf/9lo7BQqoqZwxfV0u4=", "fZbx4AWo+aeMN9Mbraux+rscCGLJEHB7hXu1e/kRgeo=", "D/x3yP7cG/SpQUwSXzpITAOA0UroT/kIiXSF3wR+jT4=", "Bcvbbu+tDL+zr1H2q26c2ATmVu7v/f7JIFweUu7qDK8=", "WajL3ZhY6ZX9meV3VTH9TkrbM31OF4o6+7foL0Uf6PI=", "cyKMKBvHkQtwb2xR5svh+YppANOVdn7X8t4DuKMxICA=", "+/VZ56MsIPxMiyLAodzKXo5TEWdQp36z89qLhpzloAo=", "daxmZaajRpZV+JxHiOYZhJBiSKN5ucqjh2WnGbHhirw=", "DOCeoSMovIvLExkhIvisow9AuNXgeWs4ECkyR6EcqYU="], "checkpoint":{"envelope":"rekor.sigstore.dev - 1193050959916656506\n1992158187\nsZ2Cpq9sCXL4mLvge3quWz8dvrjoDma3YudecTfnSfw=\n\n— rekor.sigstore.dev wNI9ajBFAiEA6Piq1feQqdbEyoF3CNxMktfdMmkVxfU3oYnhAnvAZ3sCIDfpqxQTqkIBY8rqLC90uIxZqq/qaY3J48VptJw6Dr3Y\n"}}, "canonicalizedBody":"eyJhcGlWZXJzaW9uIjoiMC4wLjEiLCJraW5kIjoiaGFzaGVkcmVrb3JkIiwic3BlYyI6eyJkYXRhIjp7Imhhc2giOnsiYWxnb3JpdGhtIjoic2hhMjU2IiwidmFsdWUiOiJjNzUyZGFkZmRlODJhOTQzMzNkNjVjYzJjMTY2OThjOTg2NzFkYzY1ZGUwNzlkNGM1ZGUwNzYyYTM2OGRkOTlkIn19LCJzaWduYXR1cmUiOnsiY29udGVudCI6Ik1FUUNJR2wzSDRnQ1NmVWRnVC95RlpGU3JDRTBFTnh1N3NTdmZNUkFJcEtqNjZmNUFpQXVSMGxvUWxlcmV0a1ZmSTFVSERpZmprS0hVNVJVOFlvZlVWMHNUWFVIRkE9PSIsInB1YmxpY0tleSI6eyJjb250ZW50IjoiTFMwdExTMUNSVWRKVGlCRFJWSlVTVVpKUTBGVVJTMHRMUzB0Q2sxSlNVaFRla05EUW5SSFowRjNTVUpCWjBsVlJVVXdNMk52T1hCc1puRkZhblkyUXpabVFrMXhVVTFXYzJOVmQwTm5XVWxMYjFwSmVtb3dSVUYzVFhjS1RucEZWazFDVFVkQk1WVkZRMmhOVFdNeWJHNWpNMUoyWTIxVmRWcEhWakpOVWpSM1NFRlpSRlpSVVVSRmVGWjZZVmRrZW1SSE9YbGFVekZ3WW01U2JBcGpiVEZzV2tkc2FHUkhWWGRJYUdOT1RXcFpkMDU2UVRSTlJHdDZUbXBGZDFkb1kwNU5hbGwzVG5wQk5FMUVhekJPYWtWM1YycEJRVTFHYTNkRmQxbElDa3R2V2tsNmFqQkRRVkZaU1V0dldrbDZhakJFUVZGalJGRm5RVVZ5V0dwaFJGRTJha0ZuT0ZSVGJXWndlRWR1WmtSaVZucFdMelJCZW5JeFpGcFNlVU1LT1VkUlIweHZhSEZ3Y3pKUFVuTk5VRWg2WTBvNVpHUnhNakJoVm1WaVJFSXJZV2hpWjNwR1FtZFdSbXB0VlRkSGJuRlBRMEptUVhkbloxaHpUVUUwUndwQk1WVmtSSGRGUWk5M1VVVkJkMGxJWjBSQlZFSm5UbFpJVTFWRlJFUkJTMEpuWjNKQ1owVkdRbEZqUkVGNlFXUkNaMDVXU0ZFMFJVWm5VVlZSVmxGMUNqTllVa2hNZGpGclRHWkdPREV2YlVwc05sVlVPWGx6ZDBoM1dVUldVakJxUWtKbmQwWnZRVlV6T1ZCd2VqRlphMFZhWWpWeFRtcHdTMFpYYVhocE5Ga0tXa1E0ZDJGM1dVUldVakJTUVZGSUwwSkhSWGRZTkZwa1lVaFNNR05JVFRaTWVUbHVZVmhTYjJSWFNYVlpNamwwVERKb01Wb3laSEJpYldSdFdWZE9iQXBNTW5Sc1kyMDFiR0pJVFhSWk1qbDBZbGhXZFdGWVVqVk1lVFZ1WVZoU2IyUlhTWFprTWpsNVlUSmFjMkl6WkhwTU1rb3hZVmQ0YTB4dWJHaGlWM2hCQ21OdFZtMWplVGx2V2xkR2EyTjVPWFJaVjJ4MVRVUnJSME5wYzBkQlVWRkNaemM0ZDBGUlJVVkxNbWd3WkVoQ2VrOXBPSFprUnpseVdsYzBkVmxYVGpBS1lWYzVkV041Tlc1aFdGSnZaRmRLTVdNeVZubFpNamwxWkVkV2RXUkROV3BpTWpCM1NIZFpTMHQzV1VKQ1FVZEVkbnBCUWtGblVWSmtNamw1WVRKYWN3cGlNMlJtV2tkc2VtTkhSakJaTW1kM1RtZFpTMHQzV1VKQ1FVZEVkbnBCUWtGM1VXOVBSMFV6VFhwQ2EwOVVXbXBOZW1NeFRtcENhbGt5V1hoYVJFNXNDazFFYkcxT01rcHBXVEpPYTFsNlp6Uk9hbWQ0VDBkWmVrMTZRVlJDWjI5eVFtZEZSVUZaVHk5TlFVVkZRa0ZXUTJSWGJITmFSRUZ5UW1kdmNrSm5SVVVLUVZsUEwwMUJSVVpDUWpGdlpGZGtibUZYTlc1YWJVWnFXbE01Y2xwWVNuVmFWM2g2VEZkT2RtSlhNVEZpYld3d1pWUkJaRUpuYjNKQ1owVkZRVmxQTHdwTlFVVkhRa0U1ZVZwWFducE1NbWhzV1ZkU2Vrd3lNV2hoVnpSM1QzZFpTMHQzV1VKQ1FVZEVkbnBCUWtOQlVYUkVRM1J2WkVoU2QyTjZiM1pNTTFKMkNtRXlWblZNYlVacVpFZHNkbUp1VFhWYU1td3dZVWhXYVdSWVRteGpiVTUyWW01U2JHSnVVWFZaTWpsMFRVY3dSME5wYzBkQlVWRkNaemM0ZDBGUmEwVUtXSGQ0WkdGSVVqQmpTRTAyVEhrNWJtRllVbTlrVjBsMVdUSTVkRXd5YURGYU1tUndZbTFrYlZsWFRteE1NblJzWTIwMWJHSklUWFJaTWpsMFlsaFdkUXBoV0ZJMVRIazFibUZZVW05a1YwbDJaREk1ZVdFeVduTmlNMlI2VERKS01XRlhlR3RNYm14b1lsZDRRV050Vm0xamVUbHZXbGRHYTJONU9YUlpWMngxQ2sxRVowZERhWE5IUVZGUlFtYzNPSGRCVVc5RlMyZDNiMDlIUlROTmVrSnJUMVJhYWsxNll6Rk9ha0pxV1RKWmVGcEVUbXhOUkd4dFRqSkthVmt5VG1zS1dYcG5ORTVxWjNoUFIxbDZUWHBCWWtKbmIzSkNaMFZGUVZsUEwwMUJSVXhDUVRCTlF6Tk9iR0pIV1hSaFJ6bDZaRWRXYTAxRlFVZERhWE5IUVZGUlFncG5OemgzUVZGM1JVMW5kM2RoU0ZJd1kwaE5Oa3g1T1c1aFdGSnZaRmRKZFZreU9YUk1NbWd4V2pKa2NHSnRaRzFaVjA1c1RESjBiR050Tld4aVNFMTBDbGt5T1hSaVdGWjFZVmhTTlUxRVowZERhWE5IUVZGUlFtYzNPSGRCVVRCRlMyZDNiMDlIUlROTmVrSnJUMVJhYWsxNll6Rk9ha0pxV1RKWmVGcEVUbXdLVFVSc2JVNHlTbWxaTWs1cldYcG5ORTVxWjNoUFIxbDZUWHBCWmtKbmIzSkNaMFZGUVZsUEwwMUJSVTlDUWtWTlJETktiRnB1VFhaaFIxWm9Xa2hOZGdwaVYwWndZbXBCWVVKbmIzSkNaMFZGUVZsUEwwMUJSVkJDUVhkTlEycEZkMDU2UlRCT2VsVXhUV3ByZDB4bldVdExkMWxDUWtGSFJIWjZRVUpGUVZGbkNrUkNOVzlrU0ZKM1kzcHZka3d5WkhCa1IyZ3hXV2sxYW1JeU1IWmhTRlp1V2pKc2RWb3lXbWhaTWxWM1IwRlpTMHQzV1VKQ1FVZEVkbnBCUWtWUlVVc0tSRUZuZVU1VVkzbE5SR013VFhwQ2RFSm5iM0pDWjBWRlFWbFBMMDFCUlZOQ1JqaE5XRmRvTUdSSVFucFBhVGgyV2pKc01HRklWbWxNYlU1MllsTTVid3BrVjJSdVlWYzFibHB0Um1wYVV6bHlXbGhLZFZwWGVIcE1WMDUyWWxjeE1XSnRiREJsVXpoMVdqSnNNR0ZJVm1sTU0yUjJZMjEwYldKSE9UTmplVGxwQ21SWGJITmFRelUxV1ZjeGMxRklTbXhhYmsxMllVZFdhRnBJVFhaaVYwWndZbXBCTkVKbmIzSkNaMFZGUVZsUEwwMUJSVlJDUTI5TlMwUm9hRTU2VFhjS1drUnJNbGw2VFROT1ZGbDNXVEpPYlUxWFVYcGFWRUUxV21wa2FWbHRUbXBhUjAwMFQwUlpORTFVYUcxTmVrMTNTVkZaUzB0M1dVSkNRVWRFZG5wQlFncEdRVkZVUkVKR00ySXpTbkphYlhoMlpERTVhMkZZVG5kWldGSnFZVVJDYTBKbmIzSkNaMFZGUVZsUEwwMUJSVlpDUmxsTlZrZG9NR1JJUW5wUGFUaDJDbG95YkRCaFNGWnBURzFPZG1KVE9XOWtWMlJ1WVZjMWJscHRSbXBhVXpseVdsaEtkVnBYZUhwTVYwNTJZbGN4TVdKdGJEQmxVemxvV1ROU2NHSXlOWG9LVEROS01XSnVUWFpOYW1jMVRYcEZlVTFFU1RCTmVrbDJXVmhTTUZwWE1YZGtTRTEyVFZSQlYwSm5iM0pDWjBWRlFWbFBMMDFCUlZkQ1FXZE5RbTVDTVFwWmJYaHdXWHBDUjBKbmIzSkNaMFZGUVZsUEwwMUJSVmxDUkdkTlRtNUtiR05IT0RaaFNGWnVXakpzZFZveVdtaFpNbFYyWVRKV2VXSnRWbk5qZVRGcUNtSXlNWFJrVnpWd1pFaHJObU50Vm0xUGJrcHNXbTVOZG1GSFZtaGFTRTEyWWxkR2NHSnFRMEpwWjFsTFMzZFpRa0pCU0ZkbFVVbEZRV2RTT0VKSWIwRUtaVUZDTWtGT01EbE5SM0pIZUhoRmVWbDRhMlZJU214dVRuZExhVk5zTmpRemFubDBMelJsUzJOdlFYWkxaVFpQUVVGQlFtNHdSVloxU2pSQlFVRlJSQXBCUldOM1VsRkphRUZMTm1wc1JqbEplSG81WlM5NFZFTjRWazlrUlVOR05UWkVlbTFpU20xT056WmFORFZJZHpWMVlpdHZRV2xDYUZOS1QzUnRMMU56Q2psWVJHSXdWREIwTjJnNFkzVndjRlF4YTJVeFNrYzFjemhqVGpoMlpYQnNNVVJCUzBKblozRm9hMnBQVUZGUlJFRjNUbTlCUkVKc1FXcEJWRmcwWW5ZS2RVTTBhSFJCU0VGWWJXNTJUMmhIZFRkWFNtRlJka1owUVdaVVZHUlBjM1ZZU1dKdVR6aFdkM2hITUhCUE5GbzVPRXB2U1ZWMk0yRXJkMUZEVFZGRFRBb3hNMjlJYW10aVVHSmxNMWxhZVRaQ1RqSmtabmhJVFVad01UVm5kMloyUzJ4dFdpOWhibUV3U1hocWFUWnphSGRSZVdrclJXOWtUM0pxVXpONlFrRTlDaTB0TFMwdFJVNUVJRU5GVWxSSlJrbERRVlJGTFMwdExTMEsifX19fQ=="}], "timestampVerificationData":{"rfc3161Timestamps":[{"signedTimestamp":"MIICyDADAgEAMIICvwYJKoZIhvcNAQcCoIICsDCCAqwCAQMxDTALBglghkgBZQMEAgEwgbcGCyqGSIb3DQEJEAEEoIGnBIGkMIGhAgEBBgkrBgEEAYO/MAIwMTANBglghkgBZQMEAgEFAAQgmbD6vUdbxXI0QN569eetYp4IOQ9dg0vxIhD7gz1ff/sCFA2iJdplolKF1skRWs4ONQT3t1ofGA8yMDI2MDcwODA5MzYxMFowAwIBAaAypDAwLjEVMBMGA1UEChMMc2lnc3RvcmUuZGV2MRUwEwYDVQQDEwxzaWdzdG9yZS10c2GgADGCAdowggHWAgEBMFEwOTEVMBMGA1UEChMMc2lnc3RvcmUuZGV2MSAwHgYDVQQDExdzaWdzdG9yZS10c2Etc2VsZnNpZ25lZAIUOhNULwyQYe68wUMvy4qOiyojiwwwCwYJYIZIAWUDBAIBoIH8MBoGCSqGSIb3DQEJAzENBgsqhkiG9w0BCRABBDAcBgkqhkiG9w0BCQUxDxcNMjYwNzA4MDkzNjEwWjAvBgkqhkiG9w0BCQQxIgQgYVOn7Ane8rL/hWMUgnVG/+xhGiVAmD1T68y13JRNSTIwgY4GCyqGSIb3DQEJEAIvMX8wfTB7MHkEIIX5J7wHq2LKw7RDVsEO/IGyxog/2nq55thw2dE6zQW3MFUwPaQ7MDkxFTATBgNVBAoTDHNpZ3N0b3JlLmRldjEgMB4GA1UEAxMXc2lnc3RvcmUtdHNhLXNlbGZzaWduZWQCFDoTVC8MkGHuvMFDL8uKjosqI4sMMAoGCCqGSM49BAMCBGYwZAIwVeNtdTaO1QKTryuXnSoZqKm6Ei1zovRzTLROkPmGpc4bHWXt1eNVy/3dj/vPnjOuAjB453HwcuBc5PtsqE+DX3oxvbSt1byD7k1zDs0dAaqO+HpqM4wUKFZG1DThEBdfof4="}]}}, "messageSignature":{"messageDigest":{"algorithm":"SHA2_256", "digest":"x1La396CqUMz1lzCwWaYyYZx3GXeB51MXeB2KjaN2Z0="}, "signature":"MEQCIGl3H4gCSfUdgT/yFZFSrCE0ENxu7sSvfMRAIpKj66f5AiAuR0loQleretkVfI1UHDifjkKHU5RU8YofUV0sTXUHFA=="}}
|