mirror of
https://github.com/pseXperiments/icicle.git
synced 2026-01-14 09:58:02 -05:00
Compare commits
8 Commits
hadar_ref8
...
v1.2.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b6dded89cd | ||
|
|
5a138367f8 | ||
|
|
a3fc01d88d | ||
|
|
d84cab79fd | ||
|
|
46d7b88f6e | ||
|
|
77a7613aa2 | ||
|
|
5a96f9937d | ||
|
|
c1a32a9879 |
2
.github/workflows/main-build.yml
vendored
2
.github/workflows/main-build.yml
vendored
@@ -80,7 +80,7 @@ jobs:
|
||||
# Building from the root workspace will build all members of the workspace by default
|
||||
run: cargo build --release --verbose
|
||||
|
||||
# TODO: Reenable once Golang bindings for v1+ is finished
|
||||
# TODO: Re-enable once Golang bindings for v1+ is finished
|
||||
# build-golang-linux:
|
||||
# name: Build Golang on Linux
|
||||
# runs-on: [self-hosted, Linux, X64, icicle]
|
||||
|
||||
2
.github/workflows/main-test.yml
vendored
2
.github/workflows/main-test.yml
vendored
@@ -75,7 +75,7 @@ jobs:
|
||||
if: needs.check-changed-files.outputs.cpp_cuda == 'true'
|
||||
run: ctest
|
||||
|
||||
# TODO: Reenable once Golang bindings for v1+ is finished
|
||||
# TODO: Re-enable once Golang bindings for v1+ is finished
|
||||
# test-golang-linux:
|
||||
# name: Test Golang on Linux
|
||||
# runs-on: [self-hosted, Linux, X64, icicle]
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
# ICICLE
|
||||
**<div align="center">ICICLE is a library for ZK acceleration using CUDA-enabled GPUs.</div>**
|
||||
|
||||
|
||||
**<div align="center">ICICLE is a library for ZK acceleration using CUDA-enabled GPUs.</div>**
|
||||
|
||||
<p align="center">
|
||||
<img alt="ICICLE" width="300" height="300" src="https://user-images.githubusercontent.com/2446179/223707486-ed8eb5ab-0616-4601-8557-12050df8ccf7.png"/>
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://discord.gg/EVVXTdt6DF">
|
||||
<img src="https://img.shields.io/discord/1063033227788423299?logo=discord" alt="Chat with us on Discord">
|
||||
@@ -13,6 +12,7 @@
|
||||
<a href="https://twitter.com/intent/follow?screen_name=Ingo_zk">
|
||||
<img src="https://img.shields.io/twitter/follow/Ingo_zk?style=social&logo=twitter" alt="Follow us on Twitter">
|
||||
</a>
|
||||
<img src="https://img.shields.io/badge/Machines%20running%20ICICLE-544-lightblue" alt="Machines running ICICLE">
|
||||
</p>
|
||||
|
||||
## Background
|
||||
|
||||
@@ -4,10 +4,10 @@ version = "1.0.0"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
icicle-cuda-runtime = { git = "https://github.com/ingonyama-zk/icicle.git", tag = "v1.0.0" }
|
||||
icicle-core = { git = "https://github.com/ingonyama-zk/icicle.git", tag = "v1.0.0" }
|
||||
icicle-bn254 = { git = "https://github.com/ingonyama-zk/icicle.git", tag = "v1.0.0", features = [ "g2" ] }
|
||||
icicle-bls12-377 = { git = "https://github.com/ingonyama-zk/icicle.git", tag = "v1.0.0" }
|
||||
icicle-cuda-runtime = { git = "https://github.com/ingonyama-zk/icicle.git", tag = "v1.1.0" }
|
||||
icicle-core = { git = "https://github.com/ingonyama-zk/icicle.git", tag = "v1.1.0" }
|
||||
icicle-bn254 = { git = "https://github.com/ingonyama-zk/icicle.git", tag = "v1.1.0", features = [ "g2" ] }
|
||||
icicle-bls12-377 = { git = "https://github.com/ingonyama-zk/icicle.git", tag = "v1.1.0" }
|
||||
ark-bn254 = { version = "0.4.0", optional = true}
|
||||
ark-bls12-377 = { version = "0.4.0", optional = true}
|
||||
ark-ec = { version = "0.4.0", optional = true}
|
||||
|
||||
@@ -4,10 +4,10 @@ version = "1.0.0"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
icicle-cuda-runtime = { git = "https://github.com/ingonyama-zk/icicle.git", tag = "v1.0.0" }
|
||||
icicle-core = { git = "https://github.com/ingonyama-zk/icicle.git", tag = "v1.0.0", features = ["arkworks"] }
|
||||
icicle-bn254 = { git = "https://github.com/ingonyama-zk/icicle.git", tag = "v1.0.0", features = ["arkworks"] }
|
||||
icicle-bls12-377 = { git = "https://github.com/ingonyama-zk/icicle.git", tag = "v1.0.0", features = ["arkworks"] }
|
||||
icicle-cuda-runtime = { git = "https://github.com/ingonyama-zk/icicle.git", tag = "v1.1.0" }
|
||||
icicle-core = { git = "https://github.com/ingonyama-zk/icicle.git", tag = "v1.1.0", features = ["arkworks"] }
|
||||
icicle-bn254 = { git = "https://github.com/ingonyama-zk/icicle.git", tag = "v1.1.0", features = ["arkworks"] }
|
||||
icicle-bls12-377 = { git = "https://github.com/ingonyama-zk/icicle.git", tag = "v1.1.0", features = ["arkworks"] }
|
||||
|
||||
ark-ff = { version = "0.4.0" }
|
||||
ark-poly = "0.4.0"
|
||||
|
||||
@@ -69,6 +69,7 @@ include_directories("${CMAKE_SOURCE_DIR}")
|
||||
|
||||
# when adding a new curve/field, append its name to the end of this list
|
||||
set(SUPPORTED_CURVES bn254;bls12_381;bls12_377;bw6_761)
|
||||
set(SUPPORTED_CURVES_WITH_POSEIDON bn254;bls12_381;bls12_377;bw6_761)
|
||||
|
||||
set(IS_CURVE_SUPPORTED FALSE)
|
||||
set(I 0)
|
||||
@@ -94,6 +95,11 @@ if (NOT BUILD_TESTS)
|
||||
|
||||
message(STATUS "Building without tests.")
|
||||
|
||||
if (CURVE IN_LIST SUPPORTED_CURVES_WITH_POSEIDON)
|
||||
list(APPEND ICICLE_SOURCES appUtils/poseidon/poseidon.cu)
|
||||
list(APPEND ICICLE_SOURCES appUtils/tree/merkle.cu)
|
||||
endif()
|
||||
|
||||
add_library(
|
||||
icicle
|
||||
utils/vec_ops.cu
|
||||
@@ -102,6 +108,7 @@ if (NOT BUILD_TESTS)
|
||||
primitives/projective.cu
|
||||
appUtils/msm/msm.cu
|
||||
appUtils/ntt/ntt.cu
|
||||
${ICICLE_SOURCES}
|
||||
)
|
||||
set_target_properties(icicle PROPERTIES OUTPUT_NAME "ingo_${CURVE}")
|
||||
target_compile_definitions(icicle PRIVATE CURVE=${CURVE})
|
||||
|
||||
1
icicle/appUtils/poseidon/.gitignore
vendored
Normal file
1
icicle/appUtils/poseidon/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
test_poseidon
|
||||
3
icicle/appUtils/poseidon/Makefile
Normal file
3
icicle/appUtils/poseidon/Makefile
Normal file
@@ -0,0 +1,3 @@
|
||||
test_poseidon: test.cu poseidon.cu kernels.cu constants.cu
|
||||
nvcc -o test_poseidon -I. -I../.. test.cu
|
||||
./test_poseidon
|
||||
115
icicle/appUtils/poseidon/constants.cu
Normal file
115
icicle/appUtils/poseidon/constants.cu
Normal file
@@ -0,0 +1,115 @@
|
||||
#include "poseidon.cuh"
|
||||
|
||||
/// These are pre-calculated constants for different curves
|
||||
#if CURVE_ID == BN254
|
||||
#include "appUtils/poseidon/constants/bn254_poseidon.h"
|
||||
using namespace poseidon_constants_bn254;
|
||||
#elif CURVE_ID == BLS12_381
|
||||
#include "appUtils/poseidon/constants/bls12_381_poseidon.h"
|
||||
using namespace poseidon_constants_bls12_381;
|
||||
#elif CURVE_ID == BLS12_377
|
||||
#include "appUtils/poseidon/constants/bls12_377_poseidon.h"
|
||||
using namespace poseidon_constants_bls12_377;
|
||||
#elif CURVE_ID == BW6_761
|
||||
#include "appUtils/poseidon/constants/bw6_761_poseidon.h"
|
||||
using namespace poseidon_constants_bw6_761;
|
||||
#endif
|
||||
|
||||
namespace poseidon {
|
||||
template <typename S>
|
||||
cudaError_t create_optimized_poseidon_constants(
|
||||
int arity,
|
||||
int full_rounds_half,
|
||||
int partial_rounds,
|
||||
const S* constants,
|
||||
device_context::DeviceContext& ctx,
|
||||
PoseidonConstants<S>* poseidon_constants)
|
||||
{
|
||||
CHK_INIT_IF_RETURN();
|
||||
cudaStream_t& stream = ctx.stream;
|
||||
int width = arity + 1;
|
||||
int round_constants_len = width * full_rounds_half * 2 + partial_rounds;
|
||||
int mds_matrix_len = width * width;
|
||||
int sparse_matrices_len = (width * 2 - 1) * partial_rounds;
|
||||
int constants_len = round_constants_len + mds_matrix_len * 2 + sparse_matrices_len;
|
||||
|
||||
// Malloc memory for copying constants
|
||||
S* d_constants;
|
||||
CHK_IF_RETURN(cudaMallocAsync(&d_constants, sizeof(S) * constants_len, stream));
|
||||
|
||||
// Copy constants
|
||||
CHK_IF_RETURN(cudaMemcpyAsync(d_constants, constants, sizeof(S) * constants_len, cudaMemcpyHostToDevice, stream));
|
||||
|
||||
S* round_constants = d_constants;
|
||||
S* mds_matrix = round_constants + round_constants_len;
|
||||
S* non_sparse_matrix = mds_matrix + mds_matrix_len;
|
||||
S* sparse_matrices = non_sparse_matrix + mds_matrix_len;
|
||||
|
||||
// Pick the domain_tag accordinaly
|
||||
// For now, we only support Merkle tree mode
|
||||
uint32_t tree_domain_tag_value = 1;
|
||||
tree_domain_tag_value = (tree_domain_tag_value << (width - 1)) - tree_domain_tag_value;
|
||||
S domain_tag = S::from(tree_domain_tag_value);
|
||||
|
||||
// Make sure all the constants have been copied
|
||||
CHK_IF_RETURN(cudaStreamSynchronize(stream));
|
||||
*poseidon_constants = {arity, partial_rounds, full_rounds_half, round_constants,
|
||||
mds_matrix, non_sparse_matrix, sparse_matrices, domain_tag};
|
||||
|
||||
return CHK_LAST();
|
||||
}
|
||||
|
||||
template <typename S>
|
||||
cudaError_t init_optimized_poseidon_constants(
|
||||
int arity, device_context::DeviceContext& ctx, PoseidonConstants<S>* poseidon_constants)
|
||||
{
|
||||
CHK_INIT_IF_RETURN();
|
||||
int full_rounds_half = FULL_ROUNDS_DEFAULT;
|
||||
int partial_rounds;
|
||||
unsigned char* constants;
|
||||
switch (arity) {
|
||||
case 2:
|
||||
constants = poseidon_constants_2;
|
||||
partial_rounds = partial_rounds_2;
|
||||
break;
|
||||
case 4:
|
||||
constants = poseidon_constants_4;
|
||||
partial_rounds = partial_rounds_4;
|
||||
break;
|
||||
case 8:
|
||||
constants = poseidon_constants_8;
|
||||
partial_rounds = partial_rounds_8;
|
||||
break;
|
||||
case 11:
|
||||
constants = poseidon_constants_11;
|
||||
partial_rounds = partial_rounds_11;
|
||||
break;
|
||||
default:
|
||||
THROW_ICICLE_ERR(
|
||||
IcicleError_t::InvalidArgument, "init_optimized_poseidon_constants: #arity must be one of [2, 4, 8, 11]");
|
||||
}
|
||||
S* h_constants = reinterpret_cast<S*>(constants);
|
||||
|
||||
create_optimized_poseidon_constants(arity, full_rounds_half, partial_rounds, h_constants, ctx, poseidon_constants);
|
||||
|
||||
return CHK_LAST();
|
||||
}
|
||||
|
||||
extern "C" cudaError_t CONCAT_EXPAND(CURVE, CreateOptimizedPoseidonConstants)(
|
||||
int arity,
|
||||
int full_rounds_half,
|
||||
int partial_rounds,
|
||||
const curve_config::scalar_t* constants,
|
||||
device_context::DeviceContext& ctx,
|
||||
PoseidonConstants<curve_config::scalar_t>* poseidon_constants)
|
||||
{
|
||||
return create_optimized_poseidon_constants<curve_config::scalar_t>(
|
||||
arity, full_rounds_half, partial_rounds, constants, ctx, poseidon_constants);
|
||||
}
|
||||
|
||||
extern "C" cudaError_t CONCAT_EXPAND(CURVE, InitOptimizedPoseidonConstants)(
|
||||
int arity, device_context::DeviceContext& ctx, PoseidonConstants<curve_config::scalar_t>* constants)
|
||||
{
|
||||
return init_optimized_poseidon_constants<curve_config::scalar_t>(arity, ctx, constants);
|
||||
}
|
||||
} // namespace poseidon
|
||||
@@ -1,54 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "../../utils/error_handler.cuh"
|
||||
#include "constants/constants_11.h"
|
||||
#include "constants/constants_2.h"
|
||||
#include "constants/constants_4.h"
|
||||
#include "constants/constants_8.h"
|
||||
#include <cassert>
|
||||
#include <map>
|
||||
|
||||
const std::string UNSUPPORTED_ARITY_MESSAGE = "Unsupported arity";
|
||||
|
||||
uint32_t partial_rounds_number_from_arity(const uint32_t arity)
|
||||
{
|
||||
switch (arity) {
|
||||
case 2:
|
||||
return 55;
|
||||
case 4:
|
||||
return 56;
|
||||
case 8:
|
||||
return 57;
|
||||
case 11:
|
||||
return 57;
|
||||
default:
|
||||
THROW_ICICLE_ERR(IcicleError_t::InvalidArgument, UNSUPPORTED_ARITY_MESSAGE);
|
||||
}
|
||||
};
|
||||
|
||||
// TO-DO: change to mapping
|
||||
const uint32_t FULL_ROUNDS_DEFAULT = 4;
|
||||
|
||||
// TO-DO: for now, the constants are only generated in bls12_381
|
||||
template <typename S>
|
||||
S* load_constants(const uint32_t arity)
|
||||
{
|
||||
unsigned char* constants;
|
||||
switch (arity) {
|
||||
case 2:
|
||||
constants = constants_2;
|
||||
break;
|
||||
case 4:
|
||||
constants = constants_4;
|
||||
break;
|
||||
case 8:
|
||||
constants = constants_8;
|
||||
break;
|
||||
case 11:
|
||||
constants = constants_11;
|
||||
break;
|
||||
default:
|
||||
THROW_ICICLE_ERR(IcicleError_t::InvalidArgument, UNSUPPORTED_ARITY_MESSAGE);
|
||||
}
|
||||
return reinterpret_cast<S*>(constants);
|
||||
}
|
||||
10809
icicle/appUtils/poseidon/constants/bls12_377_poseidon.h
Normal file
10809
icicle/appUtils/poseidon/constants/bls12_377_poseidon.h
Normal file
File diff suppressed because it is too large
Load Diff
6827
icicle/appUtils/poseidon/constants/bls12_381_poseidon.h
Normal file
6827
icicle/appUtils/poseidon/constants/bls12_381_poseidon.h
Normal file
File diff suppressed because it is too large
Load Diff
10809
icicle/appUtils/poseidon/constants/bn254_poseidon.h
Normal file
10809
icicle/appUtils/poseidon/constants/bn254_poseidon.h
Normal file
File diff suppressed because it is too large
Load Diff
16195
icicle/appUtils/poseidon/constants/bw6_761_poseidon.h
Normal file
16195
icicle/appUtils/poseidon/constants/bw6_761_poseidon.h
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,629 +0,0 @@
|
||||
unsigned char constants_2[] = {
|
||||
0xd8, 0xd3, 0x6e, 0x9d, 0x00, 0x0a, 0x32, 0xa7, 0x36, 0x8b, 0x75, 0xa2, 0x92, 0xac, 0x1e, 0x50, 0x24, 0x4a, 0xbb,
|
||||
0x1d, 0x86, 0x51, 0xbd, 0x23, 0x7a, 0xe1, 0x3a, 0xfa, 0x4b, 0x06, 0x9f, 0x66, 0x15, 0x3f, 0x9d, 0x2b, 0x84, 0xab,
|
||||
0x72, 0x6e, 0x34, 0x27, 0xac, 0x45, 0x96, 0x7c, 0xe6, 0xee, 0x6c, 0xa6, 0x4f, 0xc8, 0xf2, 0x7f, 0x53, 0xe4, 0x36,
|
||||
0xca, 0xac, 0xfb, 0xde, 0xa8, 0x61, 0x0a, 0xd5, 0x65, 0x81, 0x12, 0x71, 0x47, 0x23, 0x1e, 0x30, 0x49, 0xaa, 0x1a,
|
||||
0x4e, 0x2b, 0x29, 0x17, 0x5b, 0x27, 0xdf, 0x45, 0x8a, 0x1e, 0x1b, 0xf9, 0x09, 0x9d, 0xb8, 0x24, 0xfa, 0xce, 0xe9,
|
||||
0x21, 0xd1, 0xa0, 0x12, 0x2f, 0xca, 0x56, 0x5f, 0x2f, 0x1b, 0x40, 0x6c, 0x31, 0x90, 0x55, 0x2f, 0x1f, 0x2b, 0xd0,
|
||||
0xd2, 0xd2, 0xc9, 0x24, 0x26, 0x38, 0x05, 0x18, 0x53, 0x38, 0x1d, 0x42, 0xfc, 0x0b, 0xc8, 0xc5, 0x8b, 0x5a, 0xf3,
|
||||
0x19, 0xca, 0xff, 0xf5, 0x3b, 0xef, 0x15, 0x4e, 0xf4, 0xcc, 0xbe, 0xe8, 0x42, 0x69, 0x68, 0xf4, 0xfc, 0xd3, 0xc3,
|
||||
0xf0, 0x5d, 0x03, 0x89, 0x4a, 0xae, 0xb0, 0x13, 0x43, 0x39, 0xaa, 0x45, 0xb2, 0x41, 0x38, 0xf8, 0x20, 0x2d, 0xd1,
|
||||
0x1f, 0x3c, 0xc4, 0xaa, 0xf1, 0x40, 0xd0, 0x26, 0xe4, 0x81, 0x74, 0x41, 0xc1, 0xb4, 0xd0, 0x64, 0x8d, 0xf9, 0xdd,
|
||||
0x9a, 0x4b, 0x38, 0x45, 0x02, 0xcc, 0x01, 0x65, 0x25, 0x72, 0x24, 0x2b, 0xba, 0x3f, 0x2c, 0x1a, 0xbf, 0xc6, 0x3c,
|
||||
0xcf, 0xa1, 0xef, 0x9c, 0xda, 0x2e, 0x9b, 0x14, 0xc7, 0x81, 0x65, 0x85, 0xc3, 0x24, 0x2c, 0x65, 0xc6, 0x51, 0x3a,
|
||||
0xd3, 0xc1, 0xd1, 0xd5, 0x42, 0x8f, 0x2f, 0x3c, 0x0e, 0x61, 0xaf, 0xb8, 0xf6, 0x3c, 0x32, 0x1a, 0x9f, 0x28, 0x91,
|
||||
0x9d, 0x02, 0x18, 0x97, 0x47, 0x79, 0x21, 0xf9, 0x61, 0x40, 0x5c, 0x16, 0xa9, 0xc5, 0x6e, 0xca, 0x9f, 0x37, 0xf1,
|
||||
0x2a, 0x13, 0xf1, 0xf0, 0xf0, 0xef, 0xb4, 0x56, 0xf4, 0x08, 0x6a, 0x47, 0x52, 0x4a, 0x32, 0xbf, 0xb3, 0xab, 0xa5,
|
||||
0xdf, 0x36, 0x12, 0x63, 0x5f, 0x2e, 0xc2, 0xf4, 0x17, 0xa4, 0x0c, 0xfd, 0xeb, 0x3d, 0xe9, 0xc7, 0x1d, 0x97, 0x5e,
|
||||
0x52, 0x61, 0x75, 0x96, 0xfb, 0x11, 0x60, 0xcd, 0xf8, 0xca, 0xa8, 0x11, 0xdc, 0x6e, 0xcd, 0x59, 0xf3, 0x37, 0x41,
|
||||
0xd6, 0x61, 0xb3, 0x74, 0xe5, 0xa8, 0xc1, 0x51, 0xf5, 0xa2, 0x57, 0x2e, 0x32, 0xe4, 0x0e, 0xd2, 0xed, 0x73, 0xca,
|
||||
0x58, 0x7a, 0x81, 0x16, 0x9c, 0xa0, 0xa0, 0xc0, 0xaa, 0x65, 0xe0, 0x3f, 0x43, 0xb7, 0x03, 0xb0, 0x35, 0x84, 0x61,
|
||||
0xf6, 0x60, 0x0e, 0x18, 0xb3, 0x0a, 0xc0, 0x59, 0x98, 0x57, 0x80, 0x7e, 0x26, 0x8b, 0x26, 0x0f, 0x94, 0x44, 0xbc,
|
||||
0xc9, 0x71, 0xf8, 0x19, 0x9a, 0x3b, 0x0a, 0xea, 0x9a, 0xc0, 0x41, 0x26, 0x9b, 0x50, 0xe7, 0x5d, 0x1b, 0x59, 0x22,
|
||||
0x26, 0x79, 0x3a, 0xae, 0x39, 0x61, 0x13, 0x9c, 0x8f, 0x8e, 0xd0, 0xbf, 0x84, 0xb8, 0xca, 0x3f, 0x71, 0x41, 0x70,
|
||||
0x35, 0x88, 0x03, 0x63, 0x0d, 0xc5, 0x1a, 0xcb, 0x63, 0x11, 0x32, 0x90, 0xb6, 0xaa, 0xfb, 0xdc, 0xd9, 0xc3, 0xa1,
|
||||
0x93, 0x41, 0xe8, 0xa1, 0xfb, 0x2d, 0x88, 0x9e, 0xe6, 0x37, 0x21, 0xb2, 0xbe, 0xfc, 0x64, 0x18, 0x37, 0x87, 0xbc,
|
||||
0x36, 0xf2, 0xe4, 0x08, 0x5e, 0x87, 0x5f, 0x78, 0xbc, 0xbd, 0x4c, 0x91, 0x53, 0xb5, 0xf3, 0x3c, 0xe9, 0x8c, 0x1d,
|
||||
0xa7, 0x0a, 0x95, 0x90, 0x55, 0xfd, 0xfd, 0x61, 0xd1, 0x38, 0x21, 0xca, 0x5c, 0x8f, 0xc0, 0xc9, 0x39, 0x81, 0x8e,
|
||||
0x2d, 0x7c, 0xa7, 0xab, 0x84, 0xef, 0x09, 0xd3, 0x1f, 0xb2, 0xc8, 0xe7, 0x6a, 0x9c, 0xe5, 0x0d, 0xea, 0x15, 0x0f,
|
||||
0xdf, 0x55, 0x7e, 0x25, 0x01, 0xad, 0x36, 0xdc, 0xfe, 0x2c, 0xc2, 0xf5, 0xd1, 0x57, 0xef, 0xf2, 0x1d, 0xdd, 0x82,
|
||||
0xb0, 0x20, 0xbf, 0xfe, 0x8a, 0xa8, 0x4d, 0xb5, 0xd2, 0x03, 0x0d, 0x49, 0x43, 0xaf, 0x4a, 0xac, 0x95, 0x64, 0x6b,
|
||||
0x62, 0x6e, 0x75, 0x84, 0x85, 0x56, 0x8f, 0x99, 0x6d, 0xfa, 0xb4, 0x37, 0x30, 0xc4, 0x06, 0x82, 0x32, 0xf0, 0x86,
|
||||
0x6e, 0x5f, 0xde, 0x62, 0xa3, 0x61, 0xdc, 0x17, 0x37, 0x5c, 0xc8, 0x9b, 0x78, 0x6a, 0xf1, 0xa2, 0x77, 0x76, 0x44,
|
||||
0x93, 0xbe, 0x6b, 0x71, 0x39, 0x0a, 0x35, 0x86, 0xa3, 0x4c, 0x84, 0x0f, 0xb1, 0xbf, 0x51, 0x88, 0x18, 0x88, 0x57,
|
||||
0x09, 0x97, 0x55, 0xdf, 0x29, 0xe6, 0xff, 0xaa, 0xaf, 0x7b, 0x27, 0x29, 0xca, 0xf5, 0x11, 0x64, 0xa2, 0x2e, 0xb9,
|
||||
0x99, 0xc5, 0xc4, 0x56, 0x1b, 0x03, 0x0c, 0xf1, 0x7e, 0x9b, 0xf1, 0x8b, 0x57, 0xc7, 0x4c, 0x4a, 0x05, 0x84, 0x78,
|
||||
0x67, 0x3c, 0x82, 0xee, 0xe4, 0x55, 0xfb, 0xf2, 0x2e, 0xcb, 0x3a, 0x64, 0x88, 0x44, 0x15, 0x1b, 0x23, 0xaa, 0xe9,
|
||||
0x9a, 0x04, 0xbd, 0xb4, 0xbd, 0x34, 0x28, 0x84, 0x34, 0x55, 0x13, 0x2c, 0xbd, 0x43, 0x1c, 0x3b, 0xaf, 0x1d, 0x95,
|
||||
0x28, 0x18, 0x5f, 0xe7, 0x33, 0xa2, 0x4c, 0x58, 0xca, 0x42, 0xbe, 0x9e, 0x8e, 0x72, 0xae, 0xf1, 0x08, 0x40, 0x8f,
|
||||
0x55, 0x61, 0x68, 0xa3, 0x2e, 0xff, 0x75, 0xe7, 0x38, 0x44, 0x68, 0x4a, 0x40, 0x05, 0x3f, 0x64, 0xf2, 0xf3, 0xd7,
|
||||
0x8d, 0xd4, 0x3d, 0x69, 0x2e, 0xc9, 0x94, 0x3f, 0xc8, 0x75, 0xa1, 0xa1, 0xe5, 0x0b, 0x26, 0xec, 0x36, 0xe9, 0x29,
|
||||
0x67, 0x4b, 0xc9, 0x2b, 0x0f, 0x4b, 0xa0, 0x56, 0xaf, 0x8b, 0x81, 0xea, 0x11, 0xf5, 0x42, 0xd3, 0xf2, 0x6e, 0x91,
|
||||
0xf3, 0x35, 0x60, 0xe6, 0xa0, 0x80, 0x09, 0x45, 0xfe, 0x29, 0x4c, 0xde, 0x96, 0x76, 0x6e, 0x27, 0xfc, 0x64, 0xd3,
|
||||
0xf7, 0xb4, 0xbf, 0xfa, 0x8c, 0x13, 0x68, 0x52, 0xf7, 0x9c, 0x86, 0x74, 0xe1, 0x8a, 0x01, 0x97, 0x73, 0x69, 0x29,
|
||||
0x21, 0x0d, 0xae, 0xcf, 0xa7, 0x83, 0xf2, 0x8b, 0x93, 0x8d, 0xef, 0xf2, 0x7c, 0xc1, 0xfd, 0x50, 0xca, 0x95, 0x53,
|
||||
0x77, 0x46, 0xa8, 0xe0, 0xb9, 0x6f, 0x4e, 0xe5, 0x55, 0x35, 0x2b, 0x6b, 0x67, 0x5e, 0x4e, 0x24, 0x51, 0x85, 0xf3,
|
||||
0x19, 0x3d, 0x4c, 0x5c, 0x94, 0x7c, 0xb4, 0xe5, 0x49, 0xe8, 0xdf, 0xdd, 0x34, 0x4c, 0x64, 0x13, 0x6e, 0x67, 0x6a,
|
||||
0xc6, 0x5e, 0x82, 0x1f, 0xdc, 0x0e, 0xf6, 0x15, 0x2a, 0x6f, 0xdd, 0x3a, 0x5c, 0x7d, 0x20, 0xbf, 0xd5, 0x89, 0xa1,
|
||||
0x25, 0x2f, 0x59, 0xe7, 0xca, 0xa2, 0xb4, 0xde, 0x72, 0x2c, 0xe8, 0xe6, 0xc5, 0x3d, 0x93, 0xa5, 0xe0, 0x47, 0x7d,
|
||||
0xe5, 0x65, 0x58, 0x59, 0xec, 0x62, 0x79, 0xc5, 0x69, 0x21, 0xfb, 0x12, 0x45, 0xe7, 0xb3, 0xa0, 0x5c, 0xba, 0xfb,
|
||||
0x70, 0x38, 0x8b, 0x80, 0x95, 0x90, 0x72, 0x85, 0xf8, 0x61, 0xb3, 0x6f, 0x5f, 0x9d, 0x2d, 0x36, 0x9f, 0xe0, 0xeb,
|
||||
0xc2, 0xd2, 0xcd, 0x33, 0x5a, 0x26, 0x78, 0xa7, 0x7f, 0x24, 0x52, 0x52, 0x3a, 0xe6, 0xf6, 0xf4, 0xa0, 0x9c, 0x52,
|
||||
0x1d, 0xd5, 0x26, 0x5d, 0x9a, 0x7b, 0x9f, 0xba, 0x63, 0x6a, 0xda, 0xb9, 0xed, 0xec, 0x37, 0x8b, 0x24, 0x76, 0xcf,
|
||||
0x1d, 0xa0, 0x3e, 0x1e, 0xc7, 0x60, 0x73, 0xc5, 0x5b, 0x7f, 0x93, 0x84, 0x62, 0x9b, 0xe8, 0x28, 0x07, 0xac, 0x77,
|
||||
0xe7, 0xb3, 0x7d, 0x6f, 0x51, 0x91, 0xc7, 0xf3, 0x4d, 0x17, 0xeb, 0xe7, 0xc5, 0x31, 0x1e, 0x2d, 0x75, 0x2e, 0x30,
|
||||
0xd8, 0xe8, 0x75, 0x4c, 0x37, 0x7a, 0xd6, 0x5c, 0x75, 0x1d, 0xc0, 0xb4, 0x99, 0xa2, 0x49, 0xe0, 0x72, 0xe2, 0xb3,
|
||||
0x30, 0xed, 0x8b, 0xa7, 0x7e, 0x07, 0x79, 0x36, 0x77, 0xee, 0x15, 0x71, 0x1f, 0xe0, 0x0a, 0x98, 0x0a, 0xee, 0xcf,
|
||||
0x0c, 0x59, 0xcc, 0xc7, 0x48, 0x50, 0xd3, 0xea, 0x41, 0xe1, 0x66, 0xd4, 0x3b, 0x24, 0xe9, 0x63, 0x4c, 0x16, 0xec,
|
||||
0x51, 0x8e, 0x06, 0xc2, 0x11, 0x53, 0x58, 0x35, 0xd0, 0xd1, 0x77, 0x43, 0x59, 0x7f, 0xdb, 0x35, 0xe6, 0xea, 0x04,
|
||||
0x1b, 0x69, 0x2e, 0x03, 0x2e, 0x5e, 0xa9, 0x67, 0xc7, 0x24, 0x52, 0xef, 0x5e, 0x1d, 0x8c, 0xe8, 0xa3, 0xa4, 0x8e,
|
||||
0xc4, 0xcb, 0x5d, 0x8a, 0x57, 0x31, 0xdf, 0x3c, 0x38, 0xdf, 0xe6, 0xaf, 0x21, 0x77, 0x49, 0x02, 0xbc, 0x32, 0xde,
|
||||
0x1e, 0x9f, 0x6a, 0x95, 0x9f, 0x94, 0x3b, 0x84, 0xdc, 0xea, 0x0b, 0x09, 0x76, 0x2f, 0x93, 0x70, 0x12, 0x8c, 0xb6,
|
||||
0xd0, 0x20, 0xc3, 0xe2, 0x94, 0x8a, 0xb6, 0x2f, 0x9a, 0x03, 0xef, 0x5b, 0xc0, 0x47, 0xbf, 0xd0, 0xa7, 0x90, 0xe6,
|
||||
0x13, 0xac, 0xc9, 0x2e, 0x10, 0xef, 0x10, 0xd1, 0x81, 0x65, 0x5d, 0xfa, 0x50, 0x65, 0xc0, 0xd6, 0x59, 0x3a, 0xe0,
|
||||
0x5c, 0x94, 0xbd, 0xf8, 0xc6, 0x25, 0x85, 0x61, 0x2f, 0xa5, 0x5c, 0x0d, 0x7e, 0xe1, 0xa8, 0x04, 0x3b, 0x1f, 0x61,
|
||||
0x34, 0x4b, 0x30, 0xf3, 0x84, 0x8e, 0x89, 0xb1, 0x58, 0xe2, 0x48, 0xf4, 0x79, 0x7f, 0x5f, 0x95, 0x1d, 0xe7, 0x71,
|
||||
0x47, 0x5d, 0x43, 0x69, 0xd4, 0x7b, 0xe6, 0x87, 0x9e, 0x11, 0x12, 0x2a, 0x4f, 0xf7, 0x0c, 0xfb, 0x3c, 0x0b, 0x1d,
|
||||
0xe7, 0xa3, 0x0b, 0xdf, 0xc7, 0xd1, 0x35, 0xdb, 0x7d, 0x58, 0x7b, 0x46, 0x40, 0x3e, 0xf6, 0xc1, 0xb6, 0x22, 0x99,
|
||||
0x13, 0xd0, 0xd9, 0x3f, 0x28, 0xc5, 0xef, 0xeb, 0x6a, 0xda, 0xf5, 0xfb, 0x2d, 0x9d, 0x3c, 0x23, 0x23, 0x7d, 0x1f,
|
||||
0x81, 0x55, 0xaf, 0xd4, 0xec, 0x7b, 0x09, 0x79, 0xe1, 0x90, 0xde, 0xe3, 0xff, 0x9a, 0x13, 0x2b, 0x4e, 0x70, 0x5c,
|
||||
0x63, 0x72, 0x88, 0xfa, 0x74, 0x4f, 0xb7, 0xd1, 0x33, 0x3b, 0x8a, 0xec, 0x2e, 0x9b, 0x77, 0x0b, 0x8c, 0x3a, 0x91,
|
||||
0x2c, 0x63, 0x3c, 0x03, 0x40, 0x1e, 0x78, 0x83, 0x4c, 0xcc, 0x0a, 0x3b, 0x99, 0x8d, 0x10, 0x54, 0x79, 0x3e, 0x85,
|
||||
0x9d, 0xab, 0x2f, 0xd6, 0x9b, 0xab, 0x63, 0x85, 0x7a, 0x80, 0xe2, 0x43, 0xc0, 0x31, 0xa9, 0x77, 0x9a, 0x12, 0xf6,
|
||||
0xcb, 0x8d, 0xfb, 0x65, 0xed, 0xb7, 0x11, 0xff, 0x5c, 0xe0, 0x8f, 0x16, 0xc6, 0x9b, 0x36, 0x56, 0x2b, 0x8a, 0xe1,
|
||||
0x9b, 0xe1, 0xfc, 0x01, 0x3f, 0xa4, 0x49, 0x5d, 0x59, 0x19, 0xbd, 0xbe, 0x17, 0x49, 0xe5, 0xa1, 0xa7, 0xf7, 0x26,
|
||||
0x19, 0xa4, 0x0f, 0xd3, 0x5b, 0x74, 0xa9, 0xfe, 0x53, 0x88, 0x51, 0xa8, 0x9c, 0x3f, 0xde, 0xbd, 0x19, 0xa0, 0x40,
|
||||
0x31, 0x50, 0x1f, 0x8b, 0x92, 0x97, 0xb2, 0x1c, 0xc7, 0xb0, 0xdd, 0xd5, 0xae, 0x88, 0x92, 0x00, 0x4a, 0xd7, 0xb7,
|
||||
0xf8, 0x02, 0xaa, 0x25, 0xbb, 0x05, 0x89, 0x78, 0xda, 0x9c, 0x00, 0xb5, 0x48, 0x2c, 0x0d, 0xf3, 0xfa, 0xfc, 0x4e,
|
||||
0x6f, 0x3d, 0x96, 0x74, 0x92, 0xb5, 0x16, 0x01, 0x88, 0xb2, 0x4a, 0x9c, 0x43, 0x35, 0x75, 0xef, 0x3d, 0x6e, 0xd0,
|
||||
0x92, 0xc0, 0x24, 0xf6, 0xd6, 0xc0, 0x01, 0xef, 0x23, 0xb0, 0x6e, 0x27, 0x21, 0x5e, 0xa1, 0x8c, 0x0f, 0x69, 0xbc,
|
||||
0x09, 0x47, 0x2c, 0x13, 0x5d, 0xba, 0x32, 0x3c, 0x37, 0x62, 0x3a, 0xdf, 0x38, 0x5a, 0x17, 0xe2, 0xfc, 0xe3, 0x8e,
|
||||
0xe2, 0xd6, 0x6d, 0x50, 0x1b, 0xd1, 0xcc, 0x4b, 0x9d, 0x66, 0x0a, 0x90, 0x85, 0x01, 0x3b, 0xa2, 0x77, 0xd4, 0x95,
|
||||
0x90, 0x63, 0x49, 0x5e, 0x27, 0xe7, 0xab, 0xc5, 0xf1, 0xf9, 0xa8, 0xf2, 0x40, 0xb1, 0x14, 0x35, 0x4d, 0x69, 0x4c,
|
||||
0x51, 0x3b, 0x9b, 0x10, 0x50, 0x70, 0x34, 0xf4, 0xbe, 0x14, 0x88, 0xb5, 0x40, 0x1a, 0x68, 0x74, 0x40, 0x4c, 0xa3,
|
||||
0xa7, 0x0d, 0x32, 0x64, 0xaa, 0xef, 0xf5, 0x7b, 0x1a, 0x60, 0x1d, 0xfc, 0x33, 0xf2, 0x50, 0xc6, 0x39, 0x28, 0x53,
|
||||
0xe7, 0x98, 0xbf, 0xbd, 0x1e, 0xac, 0x80, 0x35, 0x5d, 0x7a, 0x18, 0x96, 0x8f, 0xb1, 0x41, 0xc2, 0xcb, 0x7d, 0xd0,
|
||||
0x75, 0xd4, 0xc2, 0x11, 0x78, 0xd8, 0xa1, 0x98, 0x53, 0x1c, 0x59, 0x72, 0xac, 0xc1, 0x37, 0x0f, 0x42, 0x13, 0x0b,
|
||||
0x98, 0xf9, 0x6e, 0x6f, 0x36, 0x53, 0x8d, 0x66, 0x46, 0x65, 0xf0, 0x27, 0xd3, 0xe3, 0xf0, 0x10, 0x5d, 0x1b, 0xae,
|
||||
0x8d, 0x49, 0xec, 0xe6, 0x40, 0xfc, 0xfa, 0xbe, 0x55, 0x60, 0x4b, 0xfe, 0xd0, 0xca, 0x6a, 0x45, 0xd0, 0xd5, 0xe1,
|
||||
0x5f, 0x20, 0x67, 0x09, 0x4e, 0x6d, 0x59, 0xef, 0xba, 0xec, 0x57, 0x41, 0xfa, 0x62, 0x1c, 0x54, 0xa4, 0x74, 0x46,
|
||||
0xd1, 0x91, 0x48, 0xc9, 0xa6, 0x07, 0x01, 0xd1, 0x43, 0xa0, 0xe7, 0x7f, 0x35, 0xa0, 0x6f, 0xe4, 0x57, 0xb0, 0xb8,
|
||||
0x99, 0x7c, 0x93, 0x4a, 0x0d, 0x4b, 0x0a, 0xd6, 0x24, 0xb2, 0x27, 0xd1, 0xa8, 0x2e, 0x5b, 0x3c, 0xcc, 0x17, 0xb2,
|
||||
0x8a, 0x70, 0x93, 0x2b, 0x00, 0x96, 0x2d, 0x90, 0x4d, 0x67, 0x62, 0xb8, 0xc6, 0xd1, 0x46, 0xda, 0x3b, 0x6d, 0xdf,
|
||||
0xd6, 0x03, 0xf2, 0x01, 0xa2, 0x89, 0x6c, 0x50, 0xd5, 0xf0, 0xb1, 0xd2, 0x24, 0xdd, 0x02, 0x42, 0xde, 0x1d, 0x5b,
|
||||
0x00, 0xe0, 0x5f, 0x5f, 0x31, 0xf8, 0x59, 0x9d, 0xc8, 0xa4, 0x70, 0x4d, 0x49, 0x54, 0xc3, 0x94, 0xbc, 0x58, 0x2e,
|
||||
0x03, 0x02, 0xba, 0x43, 0x2b, 0xfd, 0x0f, 0x9c, 0x0f, 0x91, 0x28, 0xf4, 0x3b, 0xe7, 0xb1, 0x3b, 0x69, 0xbd, 0x6a,
|
||||
0x8f, 0x20, 0xab, 0x8f, 0xd2, 0x5a, 0xf4, 0x00, 0x92, 0xcd, 0x45, 0xd5, 0x96, 0x37, 0x31, 0x0e, 0xfd, 0x75, 0xda,
|
||||
0xa4, 0x0c, 0x57, 0xcf, 0x7b, 0x1b, 0xf5, 0xa9, 0xcd, 0xff, 0xaf, 0xe8, 0x54, 0x52, 0x8a, 0x9e, 0x03, 0x97, 0x5e,
|
||||
0x62, 0x3f, 0x09, 0x6d, 0x54, 0x61, 0x7d, 0xfc, 0x7a, 0x33, 0x85, 0x38, 0x9a, 0x67, 0x4d, 0xb2, 0x24, 0xa7, 0x7d,
|
||||
0x33, 0xff, 0x3d, 0xe5, 0x7f, 0x7d, 0x09, 0x60, 0x87, 0xa6, 0xe4, 0x96, 0x2d, 0x3d, 0x1a, 0xa4, 0x3d, 0x2e, 0x49,
|
||||
0xcd, 0xb3, 0x62, 0x45, 0xa9, 0x84, 0xb3, 0xd8, 0xa5, 0x94, 0x07, 0xf0, 0x67, 0x39, 0xbc, 0x85, 0x9d, 0x3f, 0x14,
|
||||
0xd2, 0x53, 0x83, 0x2e, 0x85, 0x89, 0x69, 0xc7, 0xe7, 0x88, 0xbf, 0x3e, 0x1d, 0x40, 0x53, 0x95, 0xc8, 0x78, 0x03,
|
||||
0x87, 0x80, 0x93, 0x9c, 0x88, 0x32, 0x70, 0x2e, 0x91, 0x7b, 0x8f, 0x2b, 0x83, 0xd7, 0x32, 0x88, 0x5c, 0x94, 0x65,
|
||||
0x4b, 0x1a, 0x31, 0xe1, 0x16, 0x25, 0x03, 0x6e, 0xfd, 0x91, 0x7c, 0x33, 0x81, 0xcd, 0x36, 0xbb, 0xf5, 0xd2, 0x7a,
|
||||
0x65, 0x29, 0x34, 0xd7, 0x0e, 0x58, 0x75, 0xef, 0xda, 0x5e, 0xc0, 0x38, 0x16, 0x02, 0xff, 0x42, 0x1a, 0xad, 0xc5,
|
||||
0x17, 0x61, 0x89, 0x83, 0xe1, 0xc0, 0x2c, 0x5f, 0xae, 0xaa, 0x4e, 0x0f, 0x4c, 0xd6, 0xe6, 0x14, 0xf2, 0xe9, 0x06,
|
||||
0xc0, 0x16, 0x05, 0x9d, 0xd4, 0xa3, 0x32, 0x69, 0xa8, 0x8f, 0x51, 0x8c, 0x23, 0xfe, 0x66, 0x8b, 0x79, 0x79, 0xc2,
|
||||
0x6c, 0xe8, 0xff, 0x1f, 0x24, 0xf9, 0x7e, 0xe1, 0x17, 0x23, 0x65, 0xf1, 0x53, 0x8e, 0x74, 0xd5, 0xb8, 0xc8, 0x95,
|
||||
0x65, 0x00, 0xf3, 0x5f, 0x88, 0x99, 0x77, 0x8f, 0x71, 0xe5, 0xac, 0xee, 0x85, 0x4a, 0x22, 0x8b, 0x3b, 0xb9, 0xa6,
|
||||
0x71, 0x54, 0x0a, 0x03, 0x60, 0x21, 0x82, 0x2f, 0xd6, 0x20, 0x91, 0x5d, 0xd9, 0x33, 0x5e, 0x54, 0x48, 0xf7, 0xfb,
|
||||
0x6b, 0xd1, 0xef, 0x89, 0x0e, 0xd6, 0x4a, 0x18, 0x7d, 0x89, 0x19, 0x45, 0xae, 0x60, 0x2c, 0x91, 0x0a, 0x2e, 0x9c,
|
||||
0xae, 0x8b, 0xd4, 0xd8, 0x03, 0x3d, 0x33, 0xc1, 0x31, 0x68, 0x7e, 0xed, 0xa8, 0xe3, 0xa8, 0x13, 0x65, 0x64, 0xc6,
|
||||
0x5c, 0x5d, 0x60, 0xef, 0xfa, 0xf1, 0x2d, 0x33, 0x32, 0xcb, 0xc5, 0x4d, 0x0b, 0x48, 0xec, 0x84, 0x39, 0x92, 0x9a,
|
||||
0xdc, 0x60, 0x0b, 0x0a, 0x66, 0xd9, 0xaa, 0x04, 0x53, 0x84, 0xe4, 0xeb, 0x71, 0x40, 0x82, 0xc6, 0x6c, 0xb8, 0xc0,
|
||||
0xd1, 0x44, 0x9b, 0xb2, 0xb8, 0xa1, 0x5b, 0x14, 0x3d, 0xc7, 0x13, 0x1b, 0xee, 0x19, 0xb0, 0x60, 0xc5, 0x0a, 0xc6,
|
||||
0x40, 0x7f, 0x0c, 0x2e, 0x75, 0x3c, 0x6f, 0x49, 0xba, 0x38, 0x0d, 0x03, 0x54, 0x04, 0xa3, 0x51, 0x0e, 0xaf, 0x3e,
|
||||
0x34, 0xcb, 0x13, 0x22, 0x15, 0xfa, 0xc1, 0x16, 0x9e, 0x58, 0x78, 0x47, 0x9c, 0xad, 0x06, 0xcd, 0xf4, 0x10, 0xee,
|
||||
0x0d, 0x78, 0x64, 0x8d, 0x70, 0x45, 0x55, 0xc2, 0x76, 0x45, 0x40, 0xf0, 0xe2, 0xfc, 0x0e, 0x8a, 0xc4, 0x78, 0x56,
|
||||
0x7f, 0x8f, 0x05, 0x16, 0x31, 0xd3, 0x42, 0xd7, 0xfe, 0xbb, 0xaa, 0x89, 0x3c, 0x53, 0xd8, 0xa6, 0x95, 0x43, 0x72,
|
||||
0xa2, 0x00, 0x15, 0xe7, 0x83, 0xea, 0x9e, 0xad, 0x69, 0x93, 0xc5, 0x9d, 0xfc, 0xc2, 0x8d, 0x3c, 0x58, 0xd8, 0x70,
|
||||
0xd7, 0xcb, 0x65, 0x53, 0xc0, 0x9e, 0x83, 0x7e, 0x02, 0xbf, 0x6a, 0x90, 0x2f, 0xa2, 0xbe, 0x5d, 0x68, 0xeb, 0xbd,
|
||||
0xad, 0xaf, 0xee, 0x91, 0x8a, 0xeb, 0x4e, 0x98, 0xc9, 0xed, 0x24, 0x0d, 0x0d, 0x8d, 0xdf, 0x16, 0xf6, 0x8e, 0x10,
|
||||
0x59, 0x38, 0xa4, 0xd1, 0x0c, 0x09, 0x61, 0x06, 0x63, 0xcc, 0x5a, 0x84, 0x63, 0x1d, 0x90, 0xc8, 0xfb, 0x7b, 0x49,
|
||||
0xcb, 0xcf, 0x5b, 0x34, 0x47, 0x96, 0x4e, 0xb1, 0x13, 0x66, 0xd5, 0x1f, 0x18, 0x30, 0xdd, 0xd7, 0x9d, 0xb8, 0x98,
|
||||
0x41, 0xf2, 0x13, 0x1d, 0xc0, 0xbc, 0xf9, 0x03, 0x37, 0x48, 0x06, 0x89, 0xcf, 0xa8, 0x2e, 0x68, 0x3f, 0x16, 0xf3,
|
||||
0x41, 0x22, 0xfc, 0x11, 0x2d, 0xb2, 0x29, 0x5c, 0x56, 0x0f, 0xf9, 0x84, 0x22, 0xee, 0x59, 0xb3, 0x95, 0x0b, 0xc7,
|
||||
0xf0, 0x3a, 0xe4, 0x08, 0xce, 0x91, 0xdc, 0xa4, 0x1e, 0xad, 0x5e, 0x30, 0x9a, 0x0e, 0xe3, 0xb2, 0x81, 0x13, 0x97,
|
||||
0x57, 0x31, 0x8f, 0x9c, 0xe1, 0x92, 0xa3, 0xab, 0x69, 0x94, 0x02, 0x5c, 0x68, 0xe9, 0x41, 0x1a, 0xc7, 0x17, 0xde,
|
||||
0xaf, 0x77, 0xc5, 0x44, 0x2d, 0x6a, 0x2f, 0xd0, 0x16, 0x41, 0x40, 0x74, 0x57, 0x01, 0xd0, 0xaa, 0xe6, 0x70, 0x13,
|
||||
0xf5, 0x3f, 0x0a, 0x39, 0x4d, 0xb1, 0x82, 0x87, 0x9b, 0xd6, 0x2b, 0xbd, 0xec, 0xa7, 0xcb, 0xdb, 0x57, 0x4e, 0x49,
|
||||
0xa5, 0x8a, 0xa4, 0xbe, 0x83, 0xe6, 0x7c, 0x8b, 0x79, 0x4a, 0x7f, 0x39, 0x23, 0x07, 0xa8, 0xa9, 0x4e, 0xbd, 0xc3,
|
||||
0xbb, 0xcf, 0xbc, 0xe2, 0x48, 0xa3, 0x60, 0xc0, 0x2c, 0x8d, 0x60, 0x26, 0x49, 0x07, 0x92, 0x78, 0xdb, 0x99, 0x94,
|
||||
0x0e, 0x02, 0x27, 0x08, 0x9c, 0xc8, 0x23, 0x03, 0xfb, 0x6d, 0x18, 0x89, 0xe7, 0x3c, 0x08, 0xe5, 0x93, 0x31, 0xaa,
|
||||
0x06, 0xa9, 0x86, 0x70, 0x40, 0x9e, 0x08, 0x5d, 0x7d, 0x8d, 0xa8, 0xee, 0xa0, 0x31, 0x49, 0x35, 0x99, 0x78, 0xf3,
|
||||
0x97, 0x77, 0x05, 0x5f, 0xb2, 0xc8, 0xdc, 0xd8, 0xec, 0x9d, 0x48, 0xb5, 0xa4, 0x13, 0x01, 0x45, 0xe9, 0xe3, 0x84,
|
||||
0x1c, 0x01, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0xaa, 0xaa, 0x54, 0x3d, 0x54, 0x55, 0x57, 0x6d, 0x7e, 0xe2, 0x58, 0xe5,
|
||||
0x6b, 0x06, 0xb0, 0x3a, 0xd1, 0xcc, 0xda, 0xa8, 0x13, 0x71, 0x37, 0x1a, 0x49, 0x4d, 0x01, 0x00, 0x00, 0x40, 0xff,
|
||||
0xff, 0xff, 0x3f, 0xff, 0xc4, 0xfe, 0x3f, 0x02, 0x3b, 0xce, 0xfe, 0x03, 0x62, 0x39, 0x07, 0x06, 0x62, 0x6b, 0x26,
|
||||
0xf6, 0x1d, 0x36, 0x5f, 0x7e, 0x3d, 0xf2, 0x56, 0x34, 0x33, 0x33, 0x33, 0xcc, 0xcc, 0xcc, 0xcc, 0x65, 0x6a, 0x65,
|
||||
0x66, 0x9b, 0x95, 0x3e, 0x32, 0x03, 0xe8, 0x2d, 0x6c, 0x9e, 0x81, 0xef, 0x51, 0x2b, 0x4b, 0x2b, 0x4c, 0x98, 0x97,
|
||||
0x8e, 0x45, 0x01, 0x00, 0x00, 0x40, 0xff, 0xff, 0xff, 0x3f, 0xff, 0xc4, 0xfe, 0x3f, 0x02, 0x3b, 0xce, 0xfe, 0x03,
|
||||
0x62, 0x39, 0x07, 0x06, 0x62, 0x6b, 0x26, 0xf6, 0x1d, 0x36, 0x5f, 0x7e, 0x3d, 0xf2, 0x56, 0x34, 0x33, 0x33, 0x33,
|
||||
0xcc, 0xcc, 0xcc, 0xcc, 0x65, 0x6a, 0x65, 0x66, 0x9b, 0x95, 0x3e, 0x32, 0x03, 0xe8, 0x2d, 0x6c, 0x9e, 0x81, 0xef,
|
||||
0x51, 0x2b, 0x4b, 0x2b, 0x4c, 0x98, 0x97, 0x8e, 0x45, 0x01, 0x00, 0x00, 0x80, 0x54, 0x55, 0x55, 0xd5, 0xa9, 0x4c,
|
||||
0xa9, 0x2a, 0xad, 0x08, 0x1e, 0x1b, 0xaf, 0xde, 0x06, 0x08, 0x5c, 0x89, 0x05, 0x80, 0x11, 0x93, 0x58, 0x4d, 0xc5,
|
||||
0x60, 0x9b, 0x60, 0x34, 0x33, 0x33, 0x33, 0xcc, 0xcc, 0xcc, 0xcc, 0x65, 0x6a, 0x65, 0x66, 0x9b, 0x95, 0x3e, 0x32,
|
||||
0x03, 0xe8, 0x2d, 0x6c, 0x9e, 0x81, 0xef, 0x51, 0x2b, 0x4b, 0x2b, 0x4c, 0x98, 0x97, 0x8e, 0x45, 0x01, 0x00, 0x00,
|
||||
0x80, 0x54, 0x55, 0x55, 0xd5, 0xa9, 0x4c, 0xa9, 0x2a, 0xad, 0x08, 0x1e, 0x1b, 0xaf, 0xde, 0x06, 0x08, 0x5c, 0x89,
|
||||
0x05, 0x80, 0x11, 0x93, 0x58, 0x4d, 0xc5, 0x60, 0x9b, 0x60, 0x25, 0x49, 0x92, 0x24, 0xdb, 0xb6, 0x6d, 0xdb, 0x48,
|
||||
0x1a, 0x24, 0x49, 0xdc, 0x2e, 0x36, 0xaa, 0x4a, 0x62, 0x77, 0x70, 0x4b, 0x62, 0xc7, 0x57, 0x82, 0x91, 0x51, 0xe7,
|
||||
0x60, 0x54, 0x1f, 0x21, 0x01, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0xaa, 0xaa, 0x54, 0x3d, 0x54, 0x55, 0x57, 0x6d, 0x7e,
|
||||
0xe2, 0x58, 0xe5, 0x6b, 0x06, 0xb0, 0x3a, 0xd1, 0xcc, 0xda, 0xa8, 0x13, 0x71, 0x37, 0x1a, 0x49, 0x4d, 0x3e, 0x2c,
|
||||
0xe4, 0xf5, 0x63, 0xa7, 0xf2, 0x0e, 0x51, 0x85, 0x27, 0x20, 0x86, 0xec, 0x5b, 0x36, 0xe4, 0xea, 0xf3, 0x0c, 0x61,
|
||||
0xaa, 0xc6, 0x06, 0x74, 0xa3, 0xcc, 0xc1, 0x24, 0x1c, 0x32, 0x69, 0x95, 0x82, 0xd1, 0xb0, 0xf9, 0x5d, 0x48, 0x7e,
|
||||
0x90, 0xf2, 0x18, 0x4e, 0xad, 0x05, 0x11, 0x3b, 0xc9, 0xfa, 0xfe, 0xf4, 0xe4, 0x3a, 0xfc, 0xd1, 0xb8, 0x4b, 0xee,
|
||||
0xab, 0x1c, 0x80, 0x90, 0x0d, 0x01, 0x00, 0x00, 0x40, 0xff, 0xff, 0xff, 0x3f, 0xff, 0xc4, 0xfe, 0x3f, 0x02, 0x3b,
|
||||
0xce, 0xfe, 0x03, 0x62, 0x39, 0x07, 0x06, 0x62, 0x6b, 0x26, 0xf6, 0x1d, 0x36, 0x5f, 0x7e, 0x3d, 0xf2, 0x56, 0xa5,
|
||||
0xd2, 0xd6, 0x97, 0x8d, 0x8a, 0xf9, 0x2a, 0x81, 0x39, 0xfd, 0xef, 0xe5, 0xd1, 0x41, 0x7d, 0xb2, 0xa6, 0x20, 0x46,
|
||||
0x9a, 0xc4, 0x02, 0xcc, 0x8e, 0x38, 0xd8, 0xa2, 0x2d, 0x8f, 0xa7, 0x5e, 0xc2, 0x91, 0x1b, 0xf6, 0x2c, 0xb3, 0x21,
|
||||
0xed, 0x91, 0x8c, 0x3e, 0xb5, 0x8e, 0x10, 0x26, 0x1f, 0x86, 0x4d, 0xae, 0x08, 0x65, 0x72, 0x2b, 0x5d, 0x7c, 0x64,
|
||||
0x10, 0xfa, 0xc1, 0xa6, 0x20, 0x55, 0x34, 0x33, 0x33, 0x33, 0xcc, 0xcc, 0xcc, 0xcc, 0x65, 0x6a, 0x65, 0x66, 0x9b,
|
||||
0x95, 0x3e, 0x32, 0x03, 0xe8, 0x2d, 0x6c, 0x9e, 0x81, 0xef, 0x51, 0x2b, 0x4b, 0x2b, 0x4c, 0x98, 0x97, 0x8e, 0x45,
|
||||
0xc2, 0x91, 0x1b, 0xf6, 0x2c, 0xb3, 0x21, 0xed, 0x91, 0x8c, 0x3e, 0xb5, 0x8e, 0x10, 0x26, 0x1f, 0x86, 0x4d, 0xae,
|
||||
0x08, 0x65, 0x72, 0x2b, 0x5d, 0x7c, 0x64, 0x10, 0xfa, 0xc1, 0xa6, 0x20, 0x55, 0x54, 0x24, 0x25, 0x3c, 0xb1, 0x71,
|
||||
0x3e, 0xfe, 0x4e, 0xcd, 0x04, 0x70, 0xb5, 0xcd, 0x65, 0x35, 0x9b, 0xb9, 0x69, 0x70, 0xfc, 0x9e, 0xc1, 0xa4, 0x2c,
|
||||
0xe6, 0xb5, 0xd6, 0x38, 0x75, 0x07, 0x52, 0x01, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0xaa, 0xaa, 0x54, 0x3d, 0x54, 0x55,
|
||||
0x57, 0x6d, 0x7e, 0xe2, 0x58, 0xe5, 0x6b, 0x06, 0xb0, 0x3a, 0xd1, 0xcc, 0xda, 0xa8, 0x13, 0x71, 0x37, 0x1a, 0x49,
|
||||
0x4d, 0xa2, 0x92, 0xa6, 0xd6, 0xd4, 0x73, 0x2f, 0x8d, 0x27, 0x96, 0x8a, 0xc6, 0xc2, 0xbe, 0x74, 0x03, 0x5f, 0x90,
|
||||
0x8e, 0xac, 0x46, 0x55, 0x68, 0x45, 0x37, 0x1a, 0xb9, 0xf9, 0x97, 0x93, 0xd3, 0x59, 0x64, 0xe7, 0x4f, 0xee, 0x6e,
|
||||
0x02, 0x20, 0x8d, 0xbb, 0xe5, 0x84, 0x23, 0xf2, 0x41, 0x5f, 0x9f, 0xb2, 0xcf, 0xe4, 0x7d, 0xa9, 0x3a, 0xde, 0xdf,
|
||||
0xd5, 0xb6, 0x90, 0xd5, 0x24, 0xa0, 0xe0, 0x47, 0xd4, 0xfc, 0x91, 0xd8, 0xff, 0x9b, 0x40, 0xeb, 0x00, 0x2b, 0x35,
|
||||
0x8c, 0x86, 0x3c, 0x71, 0xa0, 0x84, 0xfc, 0x18, 0xf1, 0x16, 0x08, 0x99, 0xe5, 0x0c, 0x47, 0x83, 0xcb, 0x7e, 0x7f,
|
||||
0x96, 0x58, 0x72, 0x40, 0x10, 0x59, 0x28, 0x31, 0x2f, 0x0c, 0x1c, 0xa1, 0x19, 0x7f, 0x78, 0x5a, 0x5b, 0x8b, 0x40,
|
||||
0xe2, 0x52, 0xa3, 0xda, 0xea, 0xec, 0x8f, 0x71, 0xbc, 0x5d, 0x9a, 0xb2, 0xe8, 0x86, 0x6b, 0x01, 0x00, 0x00, 0x00,
|
||||
0xaa, 0xaa, 0xaa, 0xaa, 0x54, 0x3d, 0x54, 0x55, 0x57, 0x6d, 0x7e, 0xe2, 0x58, 0xe5, 0x6b, 0x06, 0xb0, 0x3a, 0xd1,
|
||||
0xcc, 0xda, 0xa8, 0x13, 0x71, 0x37, 0x1a, 0x49, 0x4d, 0xf6, 0xd4, 0x61, 0x0e, 0xe7, 0x6c, 0x28, 0x1a, 0x40, 0x1b,
|
||||
0x06, 0x94, 0x15, 0xb8, 0x36, 0x75, 0xd6, 0x24, 0xc8, 0x9b, 0x0d, 0xde, 0x46, 0xc4, 0x4d, 0x88, 0x8c, 0xb5, 0x17,
|
||||
0xfd, 0x3a, 0x6b, 0x8b, 0xfc, 0x1a, 0xd8, 0x20, 0x32, 0xfa, 0x3d, 0xe4, 0xac, 0xa3, 0xc4, 0x8c, 0xce, 0xac, 0xbf,
|
||||
0x42, 0x77, 0x63, 0x24, 0x8d, 0x33, 0x7f, 0xc1, 0x04, 0x61, 0x88, 0x6e, 0xae, 0x24, 0x52, 0x2f, 0xc6, 0xe7, 0x50,
|
||||
0x37, 0x91, 0x5c, 0xb7, 0x6a, 0x69, 0xeb, 0xfc, 0x51, 0x70, 0x80, 0xa5, 0x77, 0x83, 0xe5, 0x3e, 0xba, 0x99, 0xfa,
|
||||
0x5b, 0xfa, 0x44, 0xc2, 0x17, 0xe5, 0x7b, 0xab, 0xfe, 0x58, 0x07, 0x0a, 0x3e, 0x04, 0x21, 0x6c, 0x74, 0x03, 0x24,
|
||||
0x15, 0x15, 0x1a, 0x63, 0xa3, 0xf5, 0xaf, 0x38, 0xf9, 0xf0, 0x3f, 0x1c, 0xf2, 0x2f, 0xba, 0x9e, 0x7d, 0xac, 0x24,
|
||||
0x16, 0xc3, 0x93, 0x1e, 0x01, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0xaa, 0xaa, 0x54, 0x3d, 0x54, 0x55, 0x57, 0x6d, 0x7e,
|
||||
0xe2, 0x58, 0xe5, 0x6b, 0x06, 0xb0, 0x3a, 0xd1, 0xcc, 0xda, 0xa8, 0x13, 0x71, 0x37, 0x1a, 0x49, 0x4d, 0x7c, 0x21,
|
||||
0x29, 0xeb, 0xdd, 0xd9, 0xc2, 0xc2, 0x87, 0x30, 0x82, 0xe0, 0xe9, 0xa7, 0x35, 0x64, 0xc9, 0x67, 0xa9, 0xed, 0xd0,
|
||||
0xc5, 0x91, 0x3b, 0xc9, 0xf2, 0xd4, 0xd9, 0xc5, 0x89, 0x91, 0x4f, 0xc3, 0xd3, 0xbe, 0x3f, 0xb1, 0x31, 0x98, 0x25,
|
||||
0x25, 0x83, 0x24, 0xcd, 0x54, 0x99, 0xdb, 0x6f, 0xa7, 0x2d, 0x31, 0xc4, 0x53, 0xe1, 0x69, 0xa6, 0x35, 0xd5, 0x8d,
|
||||
0x11, 0x70, 0xfa, 0x26, 0x1e, 0x28, 0xbd, 0xfe, 0x69, 0x57, 0x63, 0x6c, 0x33, 0xe6, 0xb6, 0x10, 0x41, 0xb8, 0xbe,
|
||||
0x1f, 0xf6, 0x3a, 0xbe, 0xb5, 0x6a, 0x57, 0x66, 0xd0, 0xe4, 0x2a, 0x6b, 0xc3, 0xaa, 0x4f, 0xf2, 0xba, 0x5b, 0xd7,
|
||||
0xbe, 0xb3, 0xcc, 0x01, 0x81, 0x30, 0xdc, 0x9a, 0xd6, 0xab, 0x6a, 0x87, 0x56, 0x69, 0x23, 0xef, 0x37, 0xac, 0xbc,
|
||||
0xaf, 0xec, 0x35, 0xea, 0x74, 0xc9, 0xbf, 0x9d, 0x06, 0x76, 0xbc, 0x1d, 0x01, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0xaa,
|
||||
0xaa, 0x54, 0x3d, 0x54, 0x55, 0x57, 0x6d, 0x7e, 0xe2, 0x58, 0xe5, 0x6b, 0x06, 0xb0, 0x3a, 0xd1, 0xcc, 0xda, 0xa8,
|
||||
0x13, 0x71, 0x37, 0x1a, 0x49, 0x4d, 0xcb, 0xf6, 0x96, 0x28, 0xa7, 0x00, 0x6b, 0x60, 0x4b, 0xd1, 0x5a, 0x13, 0x03,
|
||||
0xa3, 0xda, 0x7d, 0xb6, 0x2d, 0xaa, 0x2b, 0x12, 0xf8, 0x5b, 0x0c, 0x81, 0xb4, 0x61, 0x51, 0x55, 0x40, 0x5c, 0x5e,
|
||||
0xb1, 0x5a, 0x71, 0xf9, 0x06, 0x13, 0xed, 0x2b, 0x89, 0xc0, 0x01, 0x55, 0xa8, 0xaa, 0x45, 0x36, 0xc8, 0x84, 0xfc,
|
||||
0x78, 0x69, 0x40, 0x55, 0x89, 0x88, 0xbf, 0x02, 0xd3, 0xa7, 0xd9, 0xc5, 0x48, 0x6a, 0x73, 0xaa, 0x9b, 0x54, 0x06,
|
||||
0x6c, 0x88, 0x2b, 0xef, 0x5a, 0x3f, 0x70, 0xbd, 0xb8, 0x38, 0x75, 0x9d, 0xe1, 0xf2, 0x8a, 0x8a, 0x69, 0x26, 0x6f,
|
||||
0x07, 0xf1, 0x5b, 0x00, 0x0a, 0x28, 0x41, 0x3a, 0xb1, 0xf8, 0x8d, 0xaa, 0x7f, 0xd5, 0x90, 0x34, 0xdf, 0xc9, 0xa0,
|
||||
0x59, 0x13, 0x36, 0x53, 0x28, 0x15, 0xed, 0x06, 0x7c, 0x1c, 0x2d, 0x43, 0xab, 0x50, 0x3c, 0xc9, 0x4b, 0x14, 0xda,
|
||||
0x36, 0x01, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0xaa, 0xaa, 0x54, 0x3d, 0x54, 0x55, 0x57, 0x6d, 0x7e, 0xe2, 0x58, 0xe5,
|
||||
0x6b, 0x06, 0xb0, 0x3a, 0xd1, 0xcc, 0xda, 0xa8, 0x13, 0x71, 0x37, 0x1a, 0x49, 0x4d, 0x7a, 0xc0, 0x5b, 0x5c, 0x19,
|
||||
0x50, 0x23, 0xa3, 0x8b, 0x3d, 0x80, 0x09, 0x63, 0x38, 0x5e, 0x65, 0x16, 0xd0, 0xa3, 0xa3, 0xe7, 0x28, 0x5a, 0x5f,
|
||||
0xa7, 0x0a, 0x4f, 0x0c, 0x34, 0x95, 0x26, 0x70, 0x85, 0x11, 0x97, 0x36, 0xa2, 0x76, 0x64, 0xd9, 0x7a, 0x8e, 0xa6,
|
||||
0xa1, 0x51, 0x9a, 0x89, 0xda, 0x38, 0x46, 0xd0, 0x68, 0x30, 0xde, 0x70, 0xf8, 0x88, 0x7d, 0xa9, 0x19, 0x45, 0x62,
|
||||
0xb0, 0x6f, 0xf3, 0xc4, 0xd7, 0xfd, 0x95, 0xb9, 0xd1, 0x1c, 0x7e, 0xb5, 0x58, 0xa6, 0x63, 0xaf, 0xcb, 0x4b, 0x52,
|
||||
0x83, 0x85, 0x0e, 0xed, 0x33, 0xfa, 0xb3, 0x61, 0x90, 0x61, 0x68, 0xc2, 0xba, 0x54, 0x5d, 0x23, 0xc8, 0xfb, 0x0e,
|
||||
0x7d, 0x7a, 0x8c, 0xa9, 0x09, 0x2a, 0x21, 0x4e, 0x23, 0x02, 0xf2, 0x0d, 0x84, 0xd1, 0xab, 0x8a, 0x13, 0x8c, 0x9a,
|
||||
0x6a, 0x20, 0xd2, 0x09, 0x82, 0xfb, 0x1e, 0xe6, 0x17, 0x01, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0xaa, 0xaa, 0x54, 0x3d,
|
||||
0x54, 0x55, 0x57, 0x6d, 0x7e, 0xe2, 0x58, 0xe5, 0x6b, 0x06, 0xb0, 0x3a, 0xd1, 0xcc, 0xda, 0xa8, 0x13, 0x71, 0x37,
|
||||
0x1a, 0x49, 0x4d, 0xd1, 0x0f, 0xb4, 0xbd, 0x0e, 0x68, 0x31, 0x1a, 0x30, 0xc8, 0x92, 0xd8, 0xaa, 0xcd, 0x04, 0x05,
|
||||
0x87, 0x5c, 0x49, 0x68, 0xd2, 0xba, 0x3e, 0xb2, 0x09, 0xa3, 0xb0, 0x8a, 0x59, 0xcf, 0xd2, 0x4b, 0xeb, 0xf7, 0xaa,
|
||||
0x35, 0xf6, 0x48, 0x57, 0x40, 0x6b, 0x0e, 0x26, 0x37, 0x2a, 0x91, 0x0c, 0xea, 0x3f, 0x26, 0x97, 0xc8, 0xc4, 0x4a,
|
||||
0x18, 0xd3, 0x06, 0x12, 0x93, 0xa5, 0xad, 0x9a, 0x69, 0x6a, 0xc1, 0x4d, 0x2c, 0x31, 0x45, 0x03, 0x3a, 0x2e, 0x24,
|
||||
0xd5, 0xd0, 0xdf, 0xeb, 0xdb, 0xdf, 0xd0, 0x6f, 0x3d, 0x14, 0xa8, 0x7a, 0x5f, 0x53, 0xe3, 0x9e, 0xb8, 0x68, 0x4d,
|
||||
0x91, 0xe2, 0x0a, 0x48, 0x94, 0x73, 0xd9, 0x84, 0x9a, 0x55, 0x3e, 0x42, 0x99, 0xe7, 0x1e, 0x73, 0x64, 0xd4, 0x8d,
|
||||
0x26, 0xf0, 0x16, 0x36, 0x08, 0x7b, 0xde, 0x8c, 0xe9, 0x0a, 0x27, 0x3a, 0x90, 0x6f, 0x6c, 0x90, 0x66, 0x01, 0x00,
|
||||
0x00, 0x00, 0xaa, 0xaa, 0xaa, 0xaa, 0x54, 0x3d, 0x54, 0x55, 0x57, 0x6d, 0x7e, 0xe2, 0x58, 0xe5, 0x6b, 0x06, 0xb0,
|
||||
0x3a, 0xd1, 0xcc, 0xda, 0xa8, 0x13, 0x71, 0x37, 0x1a, 0x49, 0x4d, 0xd1, 0x81, 0xc0, 0x8c, 0xc5, 0x6d, 0x18, 0x32,
|
||||
0xd7, 0x82, 0x81, 0xb4, 0x0f, 0x0b, 0x34, 0x91, 0xe1, 0xec, 0x57, 0xf2, 0x17, 0xca, 0x56, 0x15, 0x1f, 0x7d, 0xa7,
|
||||
0x27, 0x3a, 0xaf, 0xc3, 0x24, 0x0e, 0x26, 0x24, 0x5e, 0x31, 0x77, 0x45, 0xfb, 0x9c, 0x71, 0xaf, 0x19, 0x73, 0xd0,
|
||||
0x33, 0x0b, 0x22, 0xd8, 0xde, 0xd0, 0x42, 0x79, 0xc0, 0x40, 0x23, 0x44, 0x1e, 0xa3, 0xdf, 0x65, 0x48, 0x50, 0x96,
|
||||
0xdc, 0xc5, 0x98, 0x9b, 0x13, 0xa8, 0x29, 0x6e, 0x79, 0x02, 0xef, 0x50, 0xd0, 0xdf, 0x71, 0x29, 0xd3, 0xa4, 0x3a,
|
||||
0xa4, 0x13, 0xc9, 0x0f, 0xa3, 0xff, 0x73, 0x25, 0xb0, 0xb8, 0xe0, 0x07, 0x02, 0xfd, 0xb5, 0x6f, 0xb4, 0x95, 0xc5,
|
||||
0x49, 0x8b, 0x13, 0xb4, 0xb9, 0x4f, 0xba, 0xd3, 0x83, 0xc2, 0x8c, 0x7a, 0xbe, 0x9a, 0x0b, 0x7d, 0x03, 0x75, 0xf6,
|
||||
0xbd, 0x84, 0xbd, 0xc0, 0xd4, 0x33, 0x01, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0xaa, 0xaa, 0x54, 0x3d, 0x54, 0x55, 0x57,
|
||||
0x6d, 0x7e, 0xe2, 0x58, 0xe5, 0x6b, 0x06, 0xb0, 0x3a, 0xd1, 0xcc, 0xda, 0xa8, 0x13, 0x71, 0x37, 0x1a, 0x49, 0x4d,
|
||||
0x60, 0x31, 0xd7, 0xab, 0x48, 0x21, 0x3b, 0x89, 0xc4, 0x3f, 0xe9, 0x30, 0xf6, 0xbc, 0x55, 0xf0, 0xcf, 0x49, 0x4d,
|
||||
0xf3, 0x3f, 0x66, 0xbe, 0x39, 0x3c, 0xcd, 0x53, 0x36, 0xc6, 0xd6, 0x04, 0x62, 0x37, 0x64, 0x6e, 0x86, 0x83, 0x2f,
|
||||
0x1a, 0xe3, 0xd8, 0xcb, 0x6b, 0xcc, 0x18, 0x8c, 0xbc, 0x89, 0x97, 0x69, 0xa7, 0xe9, 0x61, 0x1f, 0xe6, 0x92, 0x3e,
|
||||
0x34, 0x7b, 0xfa, 0xee, 0x9d, 0xcb, 0x03, 0x26, 0x8e, 0xd5, 0xc7, 0x11, 0xfb, 0x18, 0xc6, 0xe0, 0xd0, 0x7e, 0xb7,
|
||||
0x77, 0x2c, 0x6e, 0xc0, 0x48, 0x33, 0x34, 0x11, 0x1c, 0x7d, 0x55, 0xa5, 0xca, 0xb3, 0x2d, 0xc6, 0x06, 0x59, 0x9b,
|
||||
0x27, 0x8a, 0x1a, 0xd6, 0xa4, 0x5c, 0x48, 0x9f, 0x72, 0x20, 0x69, 0xdc, 0xbd, 0xf0, 0xba, 0x39, 0x4c, 0x70, 0xa5,
|
||||
0x78, 0xb5, 0x87, 0x9c, 0x00, 0xe0, 0xc8, 0xf1, 0x8c, 0x03, 0x3a, 0x2c, 0x1c, 0x2e, 0x01, 0x00, 0x00, 0x00, 0xaa,
|
||||
0xaa, 0xaa, 0xaa, 0x54, 0x3d, 0x54, 0x55, 0x57, 0x6d, 0x7e, 0xe2, 0x58, 0xe5, 0x6b, 0x06, 0xb0, 0x3a, 0xd1, 0xcc,
|
||||
0xda, 0xa8, 0x13, 0x71, 0x37, 0x1a, 0x49, 0x4d, 0x83, 0x09, 0xd7, 0x49, 0xb5, 0x30, 0x90, 0x05, 0x98, 0x2a, 0x2f,
|
||||
0x01, 0x25, 0x9f, 0x29, 0xf4, 0xa1, 0x30, 0x62, 0x62, 0x05, 0xbb, 0xa6, 0xda, 0x2f, 0x82, 0x41, 0xad, 0x2f, 0x4a,
|
||||
0x49, 0x2f, 0x06, 0x35, 0xd8, 0x2f, 0x0c, 0xfa, 0xa5, 0x8c, 0x8e, 0xe7, 0x8a, 0x31, 0x83, 0x67, 0xf4, 0x34, 0xa2,
|
||||
0xa2, 0x88, 0x6c, 0x71, 0xc7, 0xf1, 0x4c, 0xca, 0xba, 0x0d, 0x57, 0xc8, 0xef, 0x8f, 0x42, 0x9b, 0x2d, 0x86, 0x4a,
|
||||
0x6a, 0x2c, 0xe7, 0x42, 0x56, 0xe5, 0x36, 0x46, 0xf6, 0xa6, 0x25, 0x4c, 0x83, 0xc1, 0x46, 0x19, 0x22, 0xf9, 0xcd,
|
||||
0x19, 0x31, 0x55, 0xaa, 0x2b, 0xa5, 0x59, 0x78, 0x70, 0x90, 0x84, 0x93, 0x55, 0xb8, 0x46, 0x4d, 0x54, 0xaa, 0x13,
|
||||
0x1e, 0x5f, 0x72, 0x9a, 0xb5, 0x05, 0x48, 0x28, 0x3d, 0x78, 0xaf, 0xd3, 0x25, 0x46, 0x9b, 0xd1, 0x06, 0x60, 0x74,
|
||||
0x34, 0x4e, 0x38, 0x01, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0xaa, 0xaa, 0x54, 0x3d, 0x54, 0x55, 0x57, 0x6d, 0x7e, 0xe2,
|
||||
0x58, 0xe5, 0x6b, 0x06, 0xb0, 0x3a, 0xd1, 0xcc, 0xda, 0xa8, 0x13, 0x71, 0x37, 0x1a, 0x49, 0x4d, 0x79, 0xc6, 0x8a,
|
||||
0xe3, 0xae, 0xf7, 0xaf, 0x3a, 0xb6, 0xe4, 0xd3, 0xdd, 0x69, 0x6a, 0x24, 0x45, 0x6e, 0x16, 0x97, 0x1c, 0x3e, 0xb8,
|
||||
0x34, 0x46, 0xf3, 0xd2, 0x73, 0x3f, 0x83, 0x89, 0xd2, 0x0c, 0x5a, 0x95, 0x79, 0x68, 0x8d, 0x99, 0x66, 0xad, 0xfc,
|
||||
0x2d, 0x15, 0xfb, 0x2b, 0xce, 0x6d, 0x15, 0x95, 0x82, 0x9d, 0xae, 0x31, 0x31, 0x3b, 0xd5, 0x7a, 0xe3, 0x66, 0x40,
|
||||
0x34, 0x8b, 0xc0, 0x2f, 0x94, 0x52, 0x55, 0x33, 0xce, 0x37, 0x27, 0xe3, 0x35, 0x3f, 0x63, 0x58, 0x7f, 0x92, 0x2a,
|
||||
0x4e, 0xbd, 0x43, 0x10, 0x6e, 0xc6, 0xc3, 0x86, 0x31, 0xd8, 0xb8, 0xe0, 0x39, 0x48, 0xf1, 0xa0, 0x49, 0xec, 0x14,
|
||||
0x25, 0x1b, 0xf1, 0x2d, 0x6f, 0x1a, 0x96, 0xb2, 0x0c, 0x08, 0x86, 0x9b, 0x9f, 0xfa, 0xe5, 0x1a, 0x00, 0xb6, 0x54,
|
||||
0x35, 0xcd, 0x4a, 0xb2, 0x93, 0x6e, 0x09, 0xb4, 0xb1, 0x61, 0x4c, 0x01, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0xaa, 0xaa,
|
||||
0x54, 0x3d, 0x54, 0x55, 0x57, 0x6d, 0x7e, 0xe2, 0x58, 0xe5, 0x6b, 0x06, 0xb0, 0x3a, 0xd1, 0xcc, 0xda, 0xa8, 0x13,
|
||||
0x71, 0x37, 0x1a, 0x49, 0x4d, 0xdb, 0x04, 0x30, 0x03, 0xcb, 0xf5, 0x5e, 0xe4, 0xbc, 0x0e, 0xcf, 0x6f, 0x40, 0x4d,
|
||||
0xfa, 0x18, 0x32, 0x71, 0x77, 0x86, 0x99, 0x1d, 0xb7, 0xb6, 0x34, 0x8a, 0x42, 0x0e, 0x08, 0x86, 0x14, 0x50, 0x2e,
|
||||
0x67, 0x22, 0x47, 0x1e, 0x39, 0xfb, 0x7d, 0x35, 0xc4, 0x12, 0x18, 0x0e, 0x30, 0x86, 0x19, 0xfb, 0x76, 0x16, 0x19,
|
||||
0x6d, 0x8c, 0x75, 0x95, 0x23, 0x69, 0x48, 0x28, 0xfd, 0x9b, 0x0b, 0x64, 0x91, 0xe6, 0x92, 0xd3, 0x1a, 0x8d, 0x5f,
|
||||
0x08, 0xa9, 0xee, 0x34, 0x8b, 0xe2, 0x71, 0x86, 0x8c, 0xf8, 0xa8, 0x27, 0x08, 0xd1, 0x00, 0x12, 0x77, 0xce, 0x0b,
|
||||
0xae, 0x05, 0x38, 0x38, 0x3b, 0x6f, 0xc8, 0xda, 0x82, 0x9c, 0x50, 0x72, 0x45, 0xaf, 0xad, 0x71, 0x4a, 0x6b, 0x19,
|
||||
0x6b, 0x7c, 0x1e, 0x6e, 0xe8, 0x87, 0xaa, 0x9b, 0xe5, 0x38, 0x9a, 0x22, 0x19, 0xd2, 0x9a, 0x94, 0x15, 0x70, 0x4c,
|
||||
0x01, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0xaa, 0xaa, 0x54, 0x3d, 0x54, 0x55, 0x57, 0x6d, 0x7e, 0xe2, 0x58, 0xe5, 0x6b,
|
||||
0x06, 0xb0, 0x3a, 0xd1, 0xcc, 0xda, 0xa8, 0x13, 0x71, 0x37, 0x1a, 0x49, 0x4d, 0xd6, 0xbc, 0xf5, 0x83, 0xf1, 0xfe,
|
||||
0xde, 0xf5, 0xd8, 0xae, 0xf8, 0xb3, 0x54, 0x9d, 0x69, 0x55, 0x8b, 0x2b, 0xa9, 0x5e, 0x78, 0xaf, 0x24, 0x05, 0x58,
|
||||
0x70, 0x69, 0xcd, 0x88, 0xc4, 0x0f, 0x4f, 0x68, 0xc6, 0x43, 0x2f, 0xa6, 0x92, 0xea, 0x6e, 0xb9, 0x77, 0x74, 0xae,
|
||||
0x8c, 0xfd, 0x9f, 0x79, 0xc4, 0xe1, 0x7a, 0x07, 0x6c, 0x38, 0x40, 0xdd, 0xf9, 0x1c, 0x6d, 0x19, 0xc8, 0xf1, 0xe0,
|
||||
0x18, 0xc2, 0xa5, 0xf2, 0x5f, 0xde, 0x70, 0x37, 0x1c, 0x82, 0x56, 0x5e, 0xde, 0x09, 0x70, 0x48, 0xad, 0xb8, 0x73,
|
||||
0xe7, 0x90, 0x36, 0x88, 0x4d, 0x68, 0x32, 0x0b, 0x1d, 0x77, 0x71, 0x9a, 0x21, 0x1c, 0x12, 0x3a, 0x4e, 0x82, 0x34,
|
||||
0xc7, 0xfa, 0xa9, 0x2b, 0x10, 0xa1, 0x6b, 0x9b, 0x11, 0xdb, 0x82, 0x42, 0x91, 0x02, 0x88, 0xe4, 0xba, 0x5f, 0x57,
|
||||
0xd9, 0xac, 0x30, 0x98, 0x05, 0xa8, 0x2c, 0x4d, 0x01, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0xaa, 0xaa, 0x54, 0x3d, 0x54,
|
||||
0x55, 0x57, 0x6d, 0x7e, 0xe2, 0x58, 0xe5, 0x6b, 0x06, 0xb0, 0x3a, 0xd1, 0xcc, 0xda, 0xa8, 0x13, 0x71, 0x37, 0x1a,
|
||||
0x49, 0x4d, 0xc5, 0xb5, 0x00, 0xde, 0x7e, 0x5c, 0xfe, 0x18, 0xec, 0xaa, 0x55, 0x85, 0xcb, 0x66, 0x55, 0x52, 0xad,
|
||||
0xcb, 0x74, 0x28, 0x93, 0x85, 0xd8, 0x94, 0x97, 0x4d, 0x64, 0x6e, 0xd8, 0xfe, 0x99, 0x3a, 0x57, 0x1d, 0x51, 0xc1,
|
||||
0xea, 0xdd, 0xd2, 0x38, 0xdd, 0x3d, 0xba, 0x2a, 0x71, 0x96, 0xa2, 0x97, 0xa6, 0x00, 0xc9, 0xc6, 0x65, 0xbb, 0xc6,
|
||||
0x27, 0xd6, 0x04, 0x49, 0x3a, 0x5c, 0xb3, 0xb0, 0x05, 0x05, 0xea, 0x70, 0x92, 0xe7, 0xf2, 0x43, 0x67, 0x49, 0x6b,
|
||||
0x96, 0x0f, 0x95, 0x7a, 0x15, 0x3a, 0x4f, 0x0f, 0xf5, 0xf6, 0xf1, 0x51, 0xe7, 0x12, 0x83, 0x8d, 0x2a, 0xad, 0xb3,
|
||||
0x29, 0x0b, 0x66, 0x20, 0x30, 0xf5, 0x8f, 0xb9, 0x81, 0x61, 0x2d, 0xb4, 0x44, 0xe7, 0x89, 0x89, 0x1b, 0x4b, 0xb8,
|
||||
0x90, 0x2d, 0x54, 0xa7, 0x8e, 0x58, 0x6c, 0x3c, 0xe1, 0x31, 0xba, 0x3e, 0xbf, 0xe2, 0xb4, 0x5c, 0x01, 0x00, 0x00,
|
||||
0x00, 0xaa, 0xaa, 0xaa, 0xaa, 0x54, 0x3d, 0x54, 0x55, 0x57, 0x6d, 0x7e, 0xe2, 0x58, 0xe5, 0x6b, 0x06, 0xb0, 0x3a,
|
||||
0xd1, 0xcc, 0xda, 0xa8, 0x13, 0x71, 0x37, 0x1a, 0x49, 0x4d, 0x72, 0xdc, 0xc0, 0xee, 0x8c, 0x48, 0x9a, 0x30, 0x4b,
|
||||
0x5f, 0xfc, 0x54, 0xe7, 0x0b, 0xc7, 0x1d, 0xfc, 0x66, 0x27, 0x13, 0x6d, 0x4d, 0x0c, 0x15, 0x76, 0x71, 0x51, 0xf3,
|
||||
0x25, 0xfd, 0x2c, 0x37, 0xf7, 0xc0, 0xce, 0xcc, 0xa3, 0x90, 0x0b, 0xbd, 0x5e, 0x6e, 0x09, 0x8a, 0xde, 0x6f, 0x9c,
|
||||
0x6d, 0xdc, 0xf1, 0xeb, 0x6b, 0xd0, 0x3d, 0x38, 0x8c, 0xd0, 0xbf, 0xaf, 0xbf, 0xe2, 0xb3, 0x95, 0x4f, 0x4e, 0x11,
|
||||
0x43, 0xe0, 0x90, 0x60, 0xca, 0x61, 0xc5, 0xab, 0xfc, 0xd5, 0x19, 0x02, 0xe6, 0xee, 0x32, 0xd3, 0x93, 0xc1, 0x6c,
|
||||
0x69, 0x07, 0xba, 0x37, 0x7a, 0x55, 0xed, 0xb3, 0xda, 0xbf, 0x3a, 0x56, 0x67, 0xbb, 0x94, 0xc3, 0x70, 0x3e, 0xf6,
|
||||
0x35, 0xdf, 0x5d, 0xf6, 0xec, 0x4c, 0x76, 0x88, 0x22, 0xcb, 0xb8, 0x87, 0x6f, 0x73, 0x48, 0xc5, 0xae, 0x2f, 0x89,
|
||||
0x18, 0xab, 0x89, 0x0c, 0x4e, 0x01, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0xaa, 0xaa, 0x54, 0x3d, 0x54, 0x55, 0x57, 0x6d,
|
||||
0x7e, 0xe2, 0x58, 0xe5, 0x6b, 0x06, 0xb0, 0x3a, 0xd1, 0xcc, 0xda, 0xa8, 0x13, 0x71, 0x37, 0x1a, 0x49, 0x4d, 0x62,
|
||||
0x6e, 0xaf, 0x1e, 0xc0, 0xc8, 0xa0, 0x0f, 0x41, 0x9c, 0x9a, 0x41, 0x06, 0xeb, 0x2e, 0xe5, 0x1a, 0xf4, 0x0d, 0x48,
|
||||
0x40, 0x95, 0x0e, 0xb0, 0xbb, 0xc3, 0x0c, 0x66, 0x7a, 0xd9, 0xb4, 0x0c, 0x5b, 0x03, 0x93, 0xa6, 0xa8, 0x9a, 0xea,
|
||||
0x96, 0x44, 0xcb, 0x12, 0xae, 0x40, 0x60, 0x03, 0xfc, 0xb7, 0x1b, 0x2d, 0xa0, 0x12, 0xd3, 0x30, 0x74, 0x66, 0xcc,
|
||||
0xa4, 0xfa, 0xca, 0x5b, 0x20, 0x25, 0x7f, 0x66, 0x6d, 0xad, 0x3a, 0x65, 0x13, 0xc3, 0x51, 0x00, 0x54, 0x5c, 0x61,
|
||||
0x0c, 0x76, 0xb7, 0x8b, 0xe6, 0x97, 0xb1, 0x94, 0x78, 0x4d, 0x2c, 0x33, 0xc7, 0xf0, 0x09, 0xba, 0x2d, 0xf5, 0x60,
|
||||
0x6d, 0x86, 0x75, 0x71, 0xed, 0xc9, 0x73, 0x2d, 0x73, 0x2d, 0x8a, 0xfb, 0x53, 0xa3, 0x1a, 0xc0, 0xe6, 0x8c, 0xd0,
|
||||
0x6f, 0x98, 0xfc, 0x00, 0xfe, 0x8e, 0xd9, 0x2a, 0x39, 0x5c, 0xef, 0x79, 0x1b, 0x01, 0x00, 0x00, 0x00, 0xaa, 0xaa,
|
||||
0xaa, 0xaa, 0x54, 0x3d, 0x54, 0x55, 0x57, 0x6d, 0x7e, 0xe2, 0x58, 0xe5, 0x6b, 0x06, 0xb0, 0x3a, 0xd1, 0xcc, 0xda,
|
||||
0xa8, 0x13, 0x71, 0x37, 0x1a, 0x49, 0x4d, 0x1b, 0x0e, 0xb3, 0x6e, 0xec, 0x41, 0x47, 0x9c, 0x86, 0x65, 0xba, 0x43,
|
||||
0xfd, 0xef, 0xb4, 0x42, 0xca, 0x96, 0x39, 0xec, 0x62, 0x22, 0x73, 0xf7, 0xed, 0xd3, 0x27, 0xef, 0x57, 0x7f, 0x9b,
|
||||
0x61, 0x98, 0x00, 0x63, 0xbb, 0x4f, 0x68, 0x42, 0x1e, 0xe3, 0xea, 0x08, 0xf3, 0xa4, 0xe2, 0x9e, 0x71, 0x0a, 0x45,
|
||||
0x90, 0x7f, 0x93, 0x18, 0x1d, 0x1e, 0xf1, 0x47, 0x79, 0x91, 0xe4, 0x73, 0xbf, 0x5f, 0x7e, 0xcb, 0x83, 0xde, 0xde,
|
||||
0x88, 0xa7, 0xe0, 0x65, 0x01, 0x5b, 0x94, 0x64, 0xa8, 0x12, 0xb3, 0xde, 0x22, 0x82, 0x62, 0x5d, 0x30, 0x11, 0xc7,
|
||||
0x7a, 0xa8, 0xa0, 0xd6, 0xab, 0x70, 0x88, 0x59, 0x92, 0x3f, 0xf2, 0x6b, 0x25, 0xbb, 0x11, 0xb8, 0xda, 0x29, 0x5e,
|
||||
0xde, 0x29, 0xf0, 0x50, 0x8d, 0xf2, 0x76, 0x05, 0xc0, 0xb8, 0x9f, 0xa1, 0xe7, 0x7e, 0x85, 0x07, 0xfa, 0xda, 0xed,
|
||||
0x97, 0x0a, 0x01, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0xaa, 0xaa, 0x54, 0x3d, 0x54, 0x55, 0x57, 0x6d, 0x7e, 0xe2, 0x58,
|
||||
0xe5, 0x6b, 0x06, 0xb0, 0x3a, 0xd1, 0xcc, 0xda, 0xa8, 0x13, 0x71, 0x37, 0x1a, 0x49, 0x4d, 0x0e, 0xa5, 0x09, 0x60,
|
||||
0x5e, 0xeb, 0xb2, 0x0a, 0xda, 0x15, 0x84, 0xad, 0xd7, 0xf2, 0x0e, 0x1a, 0xce, 0x93, 0xea, 0xfa, 0x1d, 0xf5, 0xfb,
|
||||
0x2d, 0x45, 0x02, 0x26, 0x89, 0xf5, 0x4a, 0x1f, 0x4a, 0x4b, 0x39, 0xfb, 0xdd, 0x38, 0xef, 0x39, 0x55, 0x55, 0xdf,
|
||||
0xc4, 0x5e, 0x23, 0x83, 0x02, 0x48, 0x60, 0xf7, 0x1b, 0xcc, 0xe8, 0x6f, 0x86, 0xdf, 0x0e, 0xcf, 0xa1, 0x3d, 0x6e,
|
||||
0xd4, 0xb4, 0x20, 0x5d, 0xee, 0xf2, 0xe7, 0x78, 0xb8, 0x40, 0xf7, 0xad, 0xe2, 0x81, 0xe7, 0xfa, 0x26, 0x92, 0x0f,
|
||||
0x24, 0x87, 0xc9, 0x44, 0x5f, 0x90, 0x9d, 0x25, 0xaa, 0xb7, 0x95, 0x76, 0x89, 0x53, 0xd5, 0x5f, 0xe8, 0xa6, 0x59,
|
||||
0xba, 0x77, 0xf1, 0x05, 0xe8, 0x2e, 0x5d, 0x24, 0x31, 0x59, 0xf8, 0x13, 0x02, 0xfe, 0x9e, 0x22, 0x7b, 0xa7, 0xb1,
|
||||
0xa1, 0xba, 0xb0, 0xb7, 0xbd, 0xd1, 0x12, 0x38, 0x99, 0x61, 0x01, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0xaa, 0xaa, 0x54,
|
||||
0x3d, 0x54, 0x55, 0x57, 0x6d, 0x7e, 0xe2, 0x58, 0xe5, 0x6b, 0x06, 0xb0, 0x3a, 0xd1, 0xcc, 0xda, 0xa8, 0x13, 0x71,
|
||||
0x37, 0x1a, 0x49, 0x4d, 0xb2, 0xcc, 0xab, 0x2f, 0x02, 0xe8, 0x24, 0xdd, 0x52, 0xf7, 0xe4, 0x98, 0x90, 0x56, 0x66,
|
||||
0x7c, 0xef, 0x7c, 0x42, 0xf3, 0x4a, 0x71, 0x47, 0x18, 0x17, 0x8c, 0x37, 0xac, 0x03, 0xde, 0xf7, 0x55, 0x75, 0xd4,
|
||||
0x7a, 0x60, 0x4e, 0xc3, 0xd0, 0xc4, 0xd4, 0x29, 0xd6, 0xc2, 0x5a, 0x10, 0x42, 0x98, 0x1f, 0xcd, 0x91, 0xe2, 0xe5,
|
||||
0xc3, 0x62, 0x26, 0x01, 0xda, 0x4b, 0xde, 0xf2, 0x37, 0xab, 0x37, 0x30, 0xaf, 0x44, 0x39, 0xb0, 0xa0, 0xa1, 0x84,
|
||||
0xbb, 0x01, 0x51, 0x77, 0x94, 0x9f, 0x1f, 0x67, 0x92, 0x39, 0x00, 0x69, 0x7a, 0x68, 0x79, 0xf4, 0x8e, 0x28, 0xde,
|
||||
0xe0, 0x4f, 0x0a, 0x4d, 0x00, 0xf0, 0xc3, 0xf8, 0x2a, 0xd3, 0x5e, 0xc2, 0x92, 0x9d, 0x1f, 0x7e, 0x77, 0x88, 0x25,
|
||||
0x9e, 0xd7, 0xaa, 0x95, 0xbd, 0x5a, 0x85, 0x61, 0x54, 0x41, 0xad, 0x8f, 0x8f, 0x02, 0x6b, 0xd5, 0x8d, 0x40, 0x01,
|
||||
0x00, 0x00, 0x00, 0xaa, 0xaa, 0xaa, 0xaa, 0x54, 0x3d, 0x54, 0x55, 0x57, 0x6d, 0x7e, 0xe2, 0x58, 0xe5, 0x6b, 0x06,
|
||||
0xb0, 0x3a, 0xd1, 0xcc, 0xda, 0xa8, 0x13, 0x71, 0x37, 0x1a, 0x49, 0x4d, 0xc0, 0xb2, 0x14, 0x11, 0x7c, 0xd7, 0xd4,
|
||||
0x99, 0xa2, 0xd1, 0x3f, 0xf2, 0xf9, 0x9c, 0x7e, 0xd9, 0x72, 0x9b, 0x8b, 0x73, 0xeb, 0x6c, 0x2b, 0xc0, 0x16, 0x3b,
|
||||
0x8d, 0xa3, 0x36, 0x95, 0xfa, 0x44, 0xd9, 0xd8, 0x58, 0xfd, 0x23, 0x67, 0x7f, 0xa2, 0xc4, 0x67, 0x69, 0xbb, 0x18,
|
||||
0x52, 0xc8, 0x38, 0xef, 0xad, 0x36, 0x79, 0x0e, 0x43, 0x17, 0x87, 0x3d, 0x1e, 0x6e, 0xf7, 0x06, 0xa5, 0xc2, 0x10,
|
||||
0x55, 0x73, 0x3a, 0x04, 0x3a, 0x32, 0x33, 0xde, 0x21, 0x54, 0xbf, 0xde, 0xd0, 0x5f, 0x2d, 0xe8, 0x3a, 0x6f, 0x9b,
|
||||
0xcb, 0x59, 0x32, 0x95, 0xb7, 0x63, 0xea, 0x6a, 0x07, 0x64, 0xa7, 0x6f, 0x3d, 0x55, 0x2a, 0x89, 0x52, 0xda, 0x87,
|
||||
0xbf, 0xaa, 0xd4, 0xbf, 0x97, 0xc0, 0xea, 0xfc, 0xc3, 0x2f, 0x2f, 0xcf, 0x8f, 0xf5, 0x7d, 0xfe, 0x0f, 0xf3, 0x13,
|
||||
0x23, 0x91, 0x76, 0xa8, 0xc5, 0x61, 0x5a, 0x01, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0xaa, 0xaa, 0x54, 0x3d, 0x54, 0x55,
|
||||
0x57, 0x6d, 0x7e, 0xe2, 0x58, 0xe5, 0x6b, 0x06, 0xb0, 0x3a, 0xd1, 0xcc, 0xda, 0xa8, 0x13, 0x71, 0x37, 0x1a, 0x49,
|
||||
0x4d, 0x5c, 0xbf, 0x5f, 0xe9, 0x15, 0x89, 0xfb, 0xdb, 0xaf, 0x98, 0x7b, 0x9c, 0x9d, 0x4f, 0x11, 0xba, 0xaf, 0x71,
|
||||
0x71, 0xc8, 0x09, 0x4e, 0xaa, 0xbe, 0x20, 0x14, 0x24, 0xc8, 0x5d, 0xa1, 0x18, 0x3b, 0xf6, 0x48, 0xd9, 0x1a, 0x75,
|
||||
0x26, 0x54, 0xcf, 0xe7, 0xbe, 0xab, 0x24, 0x8f, 0x0c, 0x9c, 0xca, 0x23, 0x33, 0xb6, 0xd6, 0x42, 0x65, 0x37, 0x5f,
|
||||
0x35, 0xe9, 0x06, 0xe3, 0x0f, 0xb6, 0x73, 0x1e, 0x4f, 0x5e, 0x94, 0x44, 0x6e, 0xdf, 0xe1, 0x2a, 0x17, 0x97, 0x9a,
|
||||
0xa1, 0x19, 0x1b, 0x3f, 0xa3, 0x25, 0x7a, 0xf1, 0x51, 0xfa, 0xdd, 0x5f, 0x80, 0x35, 0xcc, 0x90, 0x2b, 0x8e, 0xa7,
|
||||
0x5b, 0x4d, 0x9d, 0x0f, 0x13, 0xc7, 0xa6, 0x87, 0x8a, 0xce, 0xe4, 0x45, 0xf9, 0xdc, 0xbf, 0xe8, 0xbc, 0xc1, 0x5b,
|
||||
0xfa, 0x51, 0x81, 0xa9, 0x7b, 0x26, 0xa9, 0xdd, 0xa8, 0xdf, 0xcf, 0x29, 0xb3, 0xbe, 0x14, 0x01, 0x00, 0x00, 0x00,
|
||||
0xaa, 0xaa, 0xaa, 0xaa, 0x54, 0x3d, 0x54, 0x55, 0x57, 0x6d, 0x7e, 0xe2, 0x58, 0xe5, 0x6b, 0x06, 0xb0, 0x3a, 0xd1,
|
||||
0xcc, 0xda, 0xa8, 0x13, 0x71, 0x37, 0x1a, 0x49, 0x4d, 0x4d, 0x90, 0x6a, 0xf7, 0xb0, 0xff, 0x6a, 0xac, 0xaf, 0x33,
|
||||
0xf0, 0x2d, 0x6c, 0x58, 0x3e, 0x8d, 0x45, 0x5f, 0x8b, 0xd9, 0x08, 0x69, 0x0e, 0x8d, 0x4f, 0x07, 0x87, 0x5b, 0xdb,
|
||||
0x17, 0xb9, 0x4e, 0xcb, 0x48, 0x41, 0x0c, 0x88, 0xa8, 0x23, 0x79, 0x4a, 0x9d, 0x9a, 0x31, 0x72, 0xe3, 0x1b, 0xd4,
|
||||
0x4d, 0xc5, 0xb1, 0x90, 0xdb, 0x9b, 0xef, 0x03, 0xff, 0x11, 0x42, 0x29, 0xb6, 0xc6, 0xc2, 0x1e, 0x70, 0x80, 0xaf,
|
||||
0xea, 0x0a, 0xd3, 0x2d, 0xb9, 0xea, 0x6e, 0xbd, 0x5c, 0xac, 0x97, 0xa9, 0x08, 0x7d, 0x51, 0xb3, 0x72, 0x62, 0x70,
|
||||
0x4f, 0x19, 0xa9, 0xee, 0xe4, 0xc7, 0x06, 0x3f, 0xe3, 0x3d, 0x1e, 0x02, 0x0e, 0xb5, 0x57, 0x3f, 0x14, 0x23, 0xda,
|
||||
0x5b, 0xf3, 0xf3, 0xf6, 0x62, 0x4e, 0x33, 0x72, 0x41, 0x4d, 0xb1, 0x87, 0xa6, 0xee, 0x68, 0x62, 0xb1, 0x71, 0x7e,
|
||||
0xb8, 0xa9, 0xa7, 0x6f, 0x01, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0xaa, 0xaa, 0x54, 0x3d, 0x54, 0x55, 0x57, 0x6d, 0x7e,
|
||||
0xe2, 0x58, 0xe5, 0x6b, 0x06, 0xb0, 0x3a, 0xd1, 0xcc, 0xda, 0xa8, 0x13, 0x71, 0x37, 0x1a, 0x49, 0x4d, 0xa9, 0x53,
|
||||
0x42, 0x6f, 0xe4, 0x79, 0xbd, 0xc7, 0x37, 0x51, 0xc9, 0xe6, 0xfe, 0x9b, 0x63, 0x03, 0x25, 0xdb, 0xb6, 0xf9, 0xdb,
|
||||
0x80, 0x91, 0x01, 0x3f, 0xdd, 0xee, 0xe9, 0x9e, 0x60, 0xa6, 0x37, 0x43, 0x16, 0x9b, 0x92, 0x8b, 0xf9, 0xd9, 0x21,
|
||||
0xa7, 0xf9, 0x05, 0x21, 0x00, 0xaa, 0x35, 0x9c, 0x08, 0xa5, 0x66, 0xba, 0xcb, 0xe3, 0x45, 0xfd, 0x8e, 0xbb, 0x5e,
|
||||
0x97, 0x2a, 0xf9, 0x99, 0x6c, 0x8f, 0x92, 0xe8, 0x7d, 0x4f, 0x6d, 0x9c, 0x6d, 0xae, 0x17, 0xe1, 0x16, 0xde, 0x03,
|
||||
0x35, 0x01, 0x76, 0xe6, 0x5a, 0x3b, 0x45, 0xb5, 0x43, 0x21, 0x59, 0xa9, 0x87, 0x38, 0x2f, 0x07, 0x94, 0x60, 0x26,
|
||||
0xb9, 0xd2, 0xb5, 0xe3, 0x3b, 0x57, 0xa0, 0xb0, 0xb6, 0xfe, 0x10, 0x2e, 0xb6, 0xbd, 0xdf, 0x24, 0xe1, 0xc3, 0x8c,
|
||||
0xbb, 0x08, 0x62, 0x84, 0x7e, 0x37, 0x25, 0x5c, 0xd1, 0x65, 0xf2, 0x45, 0x01, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0xaa,
|
||||
0xaa, 0x54, 0x3d, 0x54, 0x55, 0x57, 0x6d, 0x7e, 0xe2, 0x58, 0xe5, 0x6b, 0x06, 0xb0, 0x3a, 0xd1, 0xcc, 0xda, 0xa8,
|
||||
0x13, 0x71, 0x37, 0x1a, 0x49, 0x4d, 0x4f, 0x72, 0x7c, 0xfb, 0xb3, 0x7d, 0x0e, 0xa5, 0x2f, 0x39, 0x76, 0x80, 0xff,
|
||||
0x08, 0xac, 0xe7, 0x21, 0x18, 0x3f, 0x03, 0xab, 0xb2, 0xde, 0x9c, 0x83, 0x47, 0xa7, 0x90, 0x1e, 0x2c, 0xa3, 0x11,
|
||||
0x14, 0x4e, 0x27, 0x52, 0x70, 0x56, 0xa6, 0x87, 0x1a, 0x45, 0x52, 0xf4, 0x9f, 0xed, 0x73, 0xb2, 0xa2, 0x01, 0x55,
|
||||
0xbd, 0x6a, 0x32, 0xd4, 0x15, 0x2e, 0x7e, 0x05, 0xbb, 0xb5, 0x27, 0x46, 0x58, 0x49, 0x2b, 0xab, 0x60, 0x30, 0xbb,
|
||||
0x6d, 0x8a, 0xd8, 0x85, 0x78, 0x25, 0x19, 0x8a, 0x9d, 0xc9, 0x3e, 0xf2, 0xb0, 0x65, 0x1b, 0xe2, 0xfd, 0x30, 0x66,
|
||||
0x4b, 0xb5, 0x6b, 0xfd, 0x7e, 0xe3, 0x1c, 0x31, 0x08, 0xa6, 0xb2, 0xda, 0x48, 0x8d, 0xeb, 0xb0, 0xac, 0xf0, 0xf5,
|
||||
0x6e, 0xe5, 0x4b, 0xc7, 0xf9, 0xfb, 0xca, 0xbd, 0x8c, 0x4e, 0x28, 0xa1, 0xe9, 0xf6, 0x7f, 0x12, 0xd3, 0x5d, 0x88,
|
||||
0x0b, 0x01, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0xaa, 0xaa, 0x54, 0x3d, 0x54, 0x55, 0x57, 0x6d, 0x7e, 0xe2, 0x58, 0xe5,
|
||||
0x6b, 0x06, 0xb0, 0x3a, 0xd1, 0xcc, 0xda, 0xa8, 0x13, 0x71, 0x37, 0x1a, 0x49, 0x4d, 0x8b, 0x4e, 0xfd, 0x3f, 0x25,
|
||||
0xc1, 0xc0, 0x59, 0x5a, 0xd5, 0x46, 0xa0, 0x79, 0x62, 0x4e, 0x29, 0xc6, 0x1f, 0x75, 0x8a, 0x8c, 0x82, 0x5e, 0x15,
|
||||
0x72, 0xd5, 0x58, 0x66, 0x81, 0x74, 0x9c, 0x40, 0x1d, 0x98, 0x69, 0x66, 0xf6, 0xcb, 0x81, 0x16, 0xd4, 0xa4, 0xbc,
|
||||
0x13, 0xd6, 0x85, 0x54, 0x5d, 0xb3, 0x1b, 0x28, 0xa3, 0x56, 0x36, 0x46, 0xf6, 0xc2, 0x98, 0x24, 0xbb, 0x35, 0xfe,
|
||||
0xa2, 0x6a, 0x0b, 0xb7, 0x27, 0x6c, 0xb4, 0xda, 0x41, 0x1b, 0x37, 0x2f, 0x76, 0x99, 0x63, 0x28, 0x79, 0xc0, 0xc5,
|
||||
0x38, 0x5d, 0xf2, 0x16, 0x23, 0x40, 0xa5, 0xb7, 0x36, 0x5a, 0xd1, 0x91, 0x4a, 0xbe, 0x6f, 0x76, 0x8e, 0x06, 0x8f,
|
||||
0x7c, 0x29, 0x10, 0x51, 0x6a, 0x42, 0xde, 0x5b, 0xed, 0x80, 0x38, 0xf4, 0xf3, 0xf2, 0x5c, 0x76, 0xf2, 0x78, 0xbd,
|
||||
0x0d, 0x0c, 0xe8, 0x78, 0x68, 0xfc, 0x7c, 0x9c, 0x55, 0x01, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0xaa, 0xaa, 0x54, 0x3d,
|
||||
0x54, 0x55, 0x57, 0x6d, 0x7e, 0xe2, 0x58, 0xe5, 0x6b, 0x06, 0xb0, 0x3a, 0xd1, 0xcc, 0xda, 0xa8, 0x13, 0x71, 0x37,
|
||||
0x1a, 0x49, 0x4d, 0x65, 0xfe, 0xff, 0xbf, 0x05, 0x2f, 0x3c, 0x1e, 0x02, 0xfa, 0x35, 0x81, 0xef, 0x42, 0xb9, 0xa8,
|
||||
0x5f, 0x6d, 0x50, 0xaf, 0x80, 0x74, 0xb5, 0x76, 0xad, 0xd0, 0x5a, 0xc0, 0x44, 0xb0, 0x49, 0x2a, 0x1c, 0x35, 0x33,
|
||||
0x93, 0x5f, 0x00, 0x08, 0x49, 0x94, 0xb7, 0xab, 0x66, 0xd3, 0xd7, 0xcc, 0xfe, 0x68, 0x9e, 0xf0, 0xae, 0x7e, 0x26,
|
||||
0x1d, 0x4a, 0x85, 0xf7, 0x0c, 0xaa, 0xd6, 0x4f, 0x0c, 0x6a, 0xde, 0xd6, 0x8b, 0xb8, 0xc0, 0xbe, 0x0b, 0xab, 0x9a,
|
||||
0x3f, 0xe4, 0x8a, 0x1c, 0x1b, 0x81, 0x1b, 0x8d, 0x6e, 0xeb, 0xa3, 0xac, 0x44, 0x9a, 0x51, 0x29, 0x50, 0x2d, 0x93,
|
||||
0xa0, 0x23, 0xb8, 0x30, 0x33, 0x15, 0xe0, 0x11, 0x8b, 0x6e, 0xe3, 0x6f, 0x62, 0xc1, 0xba, 0x8b, 0x25, 0xac, 0xd3,
|
||||
0x13, 0x47, 0xee, 0xc5, 0x56, 0x62, 0x9e, 0xbd, 0x5e, 0x03, 0xdb, 0x78, 0xde, 0x5e, 0xf9, 0xb9, 0x4e, 0x01, 0x00,
|
||||
0x00, 0x00, 0xaa, 0xaa, 0xaa, 0xaa, 0x54, 0x3d, 0x54, 0x55, 0x57, 0x6d, 0x7e, 0xe2, 0x58, 0xe5, 0x6b, 0x06, 0xb0,
|
||||
0x3a, 0xd1, 0xcc, 0xda, 0xa8, 0x13, 0x71, 0x37, 0x1a, 0x49, 0x4d, 0x00, 0x00, 0x00, 0xd0, 0x87, 0x1a, 0x49, 0x23,
|
||||
0x54, 0x58, 0x48, 0x00, 0x80, 0x87, 0x16, 0x01, 0xa0, 0xbd, 0x8c, 0x8b, 0x01, 0x1a, 0xdc, 0xfc, 0x0f, 0xe2, 0x98,
|
||||
0xa5, 0x10, 0x78, 0x25, 0x6f, 0x9b, 0x99, 0x99, 0x59, 0x82, 0xef, 0x3b, 0xc0, 0xa7, 0xd6, 0x7c, 0xb6, 0x5e, 0xe0,
|
||||
0xd5, 0x9b, 0x31, 0x32, 0xf2, 0xf9, 0xde, 0x89, 0xa6, 0x89, 0x90, 0x6d, 0xa8, 0x10, 0xb0, 0x71, 0x7a, 0x1e, 0x85,
|
||||
0xb0, 0x81, 0x18, 0x2a, 0x71, 0xb1, 0x7b, 0xbd, 0x29, 0xdc, 0x08, 0x0e, 0xc6, 0xc5, 0xfd, 0x4d, 0xce, 0x87, 0x98,
|
||||
0xd2, 0xe6, 0x0f, 0x11, 0x2f, 0x7e, 0xf0, 0xe0, 0xd8, 0x47, 0x1d, 0x04, 0xc6, 0x9b, 0xde, 0x35, 0x20, 0x57, 0x3e,
|
||||
0xd4, 0x57, 0xb8, 0x20, 0x9d, 0x95, 0xae, 0xb6, 0x21, 0x82, 0xac, 0xde, 0xdd, 0x9b, 0x60, 0x94, 0xe9, 0x4b, 0xb4,
|
||||
0x59, 0xef, 0x06, 0xa7, 0xe4, 0x65, 0x01, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0xaa, 0xaa, 0x54, 0x3d, 0x54, 0x55, 0x57,
|
||||
0x6d, 0x7e, 0xe2, 0x58, 0xe5, 0x6b, 0x06, 0xb0, 0x3a, 0xd1, 0xcc, 0xda, 0xa8, 0x13, 0x71, 0x37, 0x1a, 0x49, 0x4d,
|
||||
0x00, 0x00, 0x00, 0x30, 0xc2, 0x35, 0xb2, 0xc0, 0xe8, 0x0e, 0x8a, 0xaf, 0x28, 0x09, 0x1e, 0x7e, 0x9e, 0x37, 0x96,
|
||||
0x87, 0x92, 0x36, 0x29, 0xd7, 0x70, 0xd5, 0x84, 0xef, 0xb7, 0x50, 0x42, 0x00, 0xcd, 0xcc, 0xcc, 0x04, 0x5a, 0x14,
|
||||
0xea, 0x45, 0xb8, 0x82, 0x05, 0x94, 0x10, 0x12, 0xd3, 0x2e, 0x7d, 0x94, 0x1b, 0x04, 0x9a, 0x3c, 0x6d, 0xa5, 0x6c,
|
||||
0xbb, 0xbd, 0x4e, 0x34, 0xe1, 0xe0, 0x16, 0xcb, 0x55, 0x94, 0x0a, 0x7a, 0x18, 0xa0, 0xdd, 0x7b, 0x74, 0xd0, 0x54,
|
||||
0x3c, 0xb9, 0xcd, 0x54, 0xd0, 0x97, 0xfd, 0xfa, 0xd5, 0x19, 0xe9, 0x34, 0x4e, 0x6c, 0xa1, 0xea, 0xf3, 0x7f, 0x31,
|
||||
0x5e, 0xf8, 0x88, 0xbe, 0xec, 0x02, 0xf0, 0xce, 0x75, 0xdb, 0x51, 0xfa, 0x68, 0x41, 0x49, 0x10, 0x03, 0xab, 0xff,
|
||||
0x7f, 0x3a, 0xf5, 0x29, 0xa9, 0x1c, 0xc3, 0x3d, 0x5f, 0x4d, 0x66, 0x9b, 0x65, 0x04, 0x01, 0x00, 0x00, 0x00, 0xaa,
|
||||
0xaa, 0xaa, 0xaa, 0x54, 0x3d, 0x54, 0x55, 0x57, 0x6d, 0x7e, 0xe2, 0x58, 0xe5, 0x6b, 0x06, 0xb0, 0x3a, 0xd1, 0xcc,
|
||||
0xda, 0xa8, 0x13, 0x71, 0x37, 0x1a, 0x49, 0x4d, 0x00, 0x00, 0x00, 0x24, 0x7a, 0x63, 0x86, 0x07, 0x09, 0xeb, 0x71,
|
||||
0x66, 0xa4, 0x43, 0x09, 0xeb, 0xbc, 0x2d, 0x8c, 0x2c, 0xae, 0xeb, 0x7e, 0xde, 0xbf, 0x45, 0x0a, 0x22, 0x91, 0x27,
|
||||
0x00, 0x00, 0x67, 0x66, 0x66, 0x76, 0xa0, 0x3c, 0xc5, 0xd4, 0xd2, 0xcf, 0xd3, 0x0d, 0x97, 0x92, 0x52, 0x7c, 0xf8,
|
||||
0x5c, 0x73, 0x4d, 0xc5, 0x31, 0x62, 0x40, 0x76, 0xe7, 0xb5, 0xfb, 0xaa, 0x68, 0x8e, 0x45, 0xc2, 0xf6, 0xff, 0x3b,
|
||||
0xf3, 0x53, 0xd0, 0x30, 0x9b, 0x29, 0x1d, 0x86, 0x25, 0xbd, 0x0f, 0xf9, 0x53, 0x91, 0x10, 0x4c, 0xf5, 0x4a, 0xf3,
|
||||
0x13, 0x04, 0xf4, 0x79, 0x12, 0xc1, 0x4a, 0x58, 0x21, 0x3c, 0x74, 0xe0, 0x5d, 0x22, 0x2e, 0x60, 0x2a, 0xca, 0x3d,
|
||||
0x5f, 0xc2, 0xcb, 0xf2, 0x47, 0x71, 0xd0, 0xd6, 0x63, 0xca, 0xf3, 0xd0, 0xe8, 0x39, 0x99, 0x3b, 0xff, 0x06, 0x3e,
|
||||
0xe5, 0xcd, 0x6b, 0x01, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0xaa, 0xaa, 0x54, 0x3d, 0x54, 0x55, 0x57, 0x6d, 0x7e, 0xe2,
|
||||
0x58, 0xe5, 0x6b, 0x06, 0xb0, 0x3a, 0xd1, 0xcc, 0xda, 0xa8, 0x13, 0x71, 0x37, 0x1a, 0x49, 0x4d, 0x00, 0x00, 0x00,
|
||||
0xac, 0x99, 0x37, 0xb3, 0x60, 0xfa, 0x50, 0xcb, 0x16, 0x8f, 0x95, 0x6b, 0xcc, 0x70, 0x69, 0x74, 0x2e, 0x07, 0xd5,
|
||||
0x81, 0x98, 0xee, 0x16, 0x88, 0x9b, 0x17, 0x00, 0x00, 0x00, 0x34, 0x33, 0x33, 0xa9, 0x30, 0x56, 0xe3, 0x6e, 0x00,
|
||||
0xe2, 0x23, 0x99, 0x51, 0x52, 0x76, 0xe2, 0x4c, 0x35, 0xcc, 0xf4, 0xbe, 0x8b, 0x0f, 0xdf, 0xbf, 0xaa, 0x2a, 0xbb,
|
||||
0x59, 0x1f, 0xbe, 0x5c, 0xc0, 0x27, 0xda, 0x2d, 0x45, 0x2e, 0x95, 0x8f, 0xb7, 0x50, 0x74, 0xd9, 0xec, 0x14, 0xb8,
|
||||
0x4c, 0x0d, 0x7b, 0xc9, 0xe0, 0x02, 0xd1, 0x9e, 0x56, 0xc9, 0x27, 0xf7, 0xa8, 0xa6, 0xa1, 0xdc, 0x38, 0x3f, 0xff,
|
||||
0xf9, 0x30, 0xfa, 0x8c, 0xc8, 0xab, 0x60, 0x86, 0xf0, 0x52, 0xc4, 0x01, 0xc2, 0x9c, 0xb3, 0x42, 0x51, 0x52, 0x54,
|
||||
0x35, 0x83, 0x05, 0xb2, 0xd5, 0xc6, 0x9b, 0x7a, 0x43, 0xa6, 0x6c, 0x01, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0xaa, 0xaa,
|
||||
0x54, 0x3d, 0x54, 0x55, 0x57, 0x6d, 0x7e, 0xe2, 0x58, 0xe5, 0x6b, 0x06, 0xb0, 0x3a, 0xd1, 0xcc, 0xda, 0xa8, 0x13,
|
||||
0x71, 0x37, 0x1a, 0x49, 0x4d, 0x00, 0x00, 0x00, 0xa5, 0xd1, 0xee, 0x7c, 0xd0, 0xba, 0xcb, 0x9d, 0x26, 0x7f, 0xd1,
|
||||
0xed, 0xba, 0xb3, 0x89, 0xf0, 0x52, 0xc2, 0x4f, 0x0c, 0xf0, 0x23, 0xdd, 0x15, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x9a,
|
||||
0x99, 0x99, 0xe5, 0x87, 0xd2, 0xdc, 0x99, 0xaf, 0xaf, 0x6f, 0xca, 0x7f, 0x10, 0x1c, 0x8b, 0x6e, 0xb8, 0xd8, 0xc5,
|
||||
0x9e, 0xd0, 0x03, 0xce, 0x57, 0x95, 0xbd, 0xcc, 0xba, 0x0f, 0x5f, 0x2e, 0xbf, 0x91, 0x50, 0x10, 0xfb, 0xe2, 0x60,
|
||||
0x0a, 0x57, 0xb1, 0xc7, 0xdb, 0xc3, 0x18, 0x08, 0x02, 0x48, 0xc8, 0xea, 0xa0, 0x46, 0x32, 0xaa, 0x31, 0x46, 0x05,
|
||||
0xbb, 0xbc, 0x03, 0x8d, 0xee, 0x36, 0xff, 0xa5, 0x22, 0x99, 0x0d, 0xd2, 0x0a, 0x51, 0x1a, 0x45, 0x34, 0x44, 0x68,
|
||||
0x5d, 0x72, 0xde, 0x20, 0x7d, 0xa1, 0xa1, 0x77, 0xce, 0xd3, 0xc1, 0x91, 0xa1, 0x29, 0x1e, 0xc6, 0xe3, 0x35, 0x14,
|
||||
0x01, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0xaa, 0xaa, 0x54, 0x3d, 0x54, 0x55, 0x57, 0x6d, 0x7e, 0xe2, 0x58, 0xe5, 0x6b,
|
||||
0x06, 0xb0, 0x3a, 0xd1, 0xcc, 0xda, 0xa8, 0x13, 0x71, 0x37, 0x1a, 0x49, 0x4d, 0x00, 0x00, 0x00, 0x83, 0x1e, 0x97,
|
||||
0x8a, 0xf6, 0x06, 0xe2, 0xcb, 0xfe, 0xa5, 0x10, 0x1f, 0x59, 0x8b, 0xd6, 0x2f, 0x75, 0xeb, 0x3d, 0xff, 0xdf, 0x6e,
|
||||
0x67, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0xcd, 0xcc, 0x4c, 0xbc, 0x97, 0xb3, 0x89, 0x2c, 0x3e, 0x8b, 0x8b, 0xaf,
|
||||
0x9b, 0x36, 0xe5, 0x38, 0x1c, 0x8d, 0x76, 0x2b, 0xf5, 0x49, 0xe6, 0x15, 0x6c, 0x21, 0xaf, 0x6e, 0xdd, 0x87, 0x2f,
|
||||
0x17, 0xee, 0x4e, 0x3a, 0xda, 0x8f, 0x49, 0x3f, 0xd1, 0xcc, 0xc1, 0xd6, 0x95, 0x9e, 0x09, 0x52, 0x40, 0xab, 0xac,
|
||||
0x43, 0xc0, 0x04, 0x7a, 0x13, 0x51, 0x40, 0xae, 0xd1, 0x27, 0x84, 0xee, 0xf6, 0x4e, 0x8e, 0xd8, 0x03, 0x5c, 0x37,
|
||||
0x93, 0x2c, 0x43, 0x49, 0xac, 0x48, 0xd9, 0xa0, 0x82, 0x6b, 0x9f, 0x73, 0x22, 0xc6, 0x35, 0x95, 0x41, 0x89, 0x43,
|
||||
0xb1, 0x1f, 0x04, 0xfa, 0x25, 0x24, 0x59, 0x31, 0x01, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0xaa, 0xaa, 0x54, 0x3d, 0x54,
|
||||
0x55, 0x57, 0x6d, 0x7e, 0xe2, 0x58, 0xe5, 0x6b, 0x06, 0xb0, 0x3a, 0xd1, 0xcc, 0xda, 0xa8, 0x13, 0x71, 0x37, 0x1a,
|
||||
0x49, 0x4d, 0x00, 0x00, 0x40, 0xe4, 0x16, 0xab, 0x32, 0x30, 0xf2, 0x5a, 0x04, 0x1d, 0x4c, 0x5c, 0xea, 0xfe, 0x39,
|
||||
0xbb, 0xe4, 0x26, 0x4f, 0x5e, 0x35, 0xa6, 0x03, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x67, 0x66, 0x66, 0xdb,
|
||||
0x44, 0x0e, 0xbd, 0xc1, 0x9b, 0x8c, 0x59, 0xb7, 0xb9, 0xc3, 0xb0, 0x7d, 0x2a, 0x27, 0x26, 0x19, 0x9e, 0xa2, 0x35,
|
||||
0xe4, 0x38, 0x45, 0x2b, 0x4c, 0x98, 0x97, 0x8e, 0x45, 0xbb, 0xda, 0xd7, 0xf5, 0xdc, 0xf5, 0xee, 0x05, 0x0b, 0x14,
|
||||
0x99, 0x1d, 0x2c, 0x77, 0x0b, 0xa8, 0xe0, 0x4c, 0x30, 0xd5, 0xe7, 0x25, 0xa5, 0x00, 0x81, 0x5f, 0xbf, 0x8a, 0x0c,
|
||||
0x7c, 0xdd, 0x18, 0xb0, 0x6c, 0xf4, 0x8f, 0x59, 0x92, 0xf6, 0x79, 0xf6, 0x8d, 0x23, 0xf9, 0xaa, 0xc2, 0x33, 0xf1,
|
||||
0x15, 0xa6, 0x48, 0x92, 0x1c, 0xd8, 0x44, 0x2d, 0xe3, 0xdf, 0x33, 0x4c, 0xab, 0x74, 0x9b, 0x1a, 0x01, 0x00, 0x00,
|
||||
0x00, 0xaa, 0xaa, 0xaa, 0xaa, 0x54, 0x3d, 0x54, 0x55, 0x57, 0x6d, 0x7e, 0xe2, 0x58, 0xe5, 0x6b, 0x06, 0xb0, 0x3a,
|
||||
0xd1, 0xcc, 0xda, 0xa8, 0x13, 0x71, 0x37, 0x1a, 0x49, 0x4d, 0x00, 0x00, 0xc0, 0x5a, 0x43, 0x4f, 0x54, 0x90, 0x5b,
|
||||
0x8f, 0x29, 0xf1, 0xbe, 0xb3, 0x8e, 0xbf, 0x2b, 0x63, 0x9b, 0xa4, 0x6d, 0x29, 0xe3, 0xfd, 0x02, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x34, 0x33, 0x93, 0x51, 0xa5, 0xa4, 0x2f, 0xc2, 0xf4, 0x64, 0x4f, 0xb1, 0x7e, 0xa0, 0x7e,
|
||||
0xc7, 0x62, 0x51, 0xe8, 0xcd, 0xbb, 0xdf, 0x39, 0x36, 0x36, 0x64, 0xe4, 0xba, 0x75, 0x1f, 0xbe, 0x5c, 0x26, 0xa3,
|
||||
0x44, 0xc5, 0xda, 0xd1, 0xc0, 0x1f, 0x86, 0x3b, 0x67, 0x70, 0xe2, 0x82, 0x02, 0x91, 0x2b, 0x40, 0xb0, 0x46, 0xe2,
|
||||
0xcf, 0xe7, 0x51, 0x2b, 0x63, 0x28, 0xac, 0x8c, 0x0d, 0x7e, 0x2f, 0xce, 0x8f, 0x89, 0x09, 0xf4, 0x60, 0xb2, 0x30,
|
||||
0xa1, 0xfd, 0x80, 0xf7, 0xf8, 0x2d, 0xa8, 0xa8, 0x0f, 0x4d, 0x4e, 0xaa, 0x92, 0x83, 0x95, 0xa1, 0x6b, 0x2c, 0xb2,
|
||||
0x3e, 0x6f, 0x3e, 0x33, 0x5c, 0x01, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0xaa, 0xaa, 0x54, 0x3d, 0x54, 0x55, 0x57, 0x6d,
|
||||
0x7e, 0xe2, 0x58, 0xe5, 0x6b, 0x06, 0xb0, 0x3a, 0xd1, 0xcc, 0xda, 0xa8, 0x13, 0x71, 0x37, 0x1a, 0x49, 0x4d, 0x00,
|
||||
0x00, 0xd0, 0xb0, 0xb1, 0x11, 0x5d, 0x5f, 0x5d, 0xc3, 0x95, 0x1a, 0x6e, 0xc2, 0xfe, 0xd5, 0xed, 0x59, 0xd2, 0x9f,
|
||||
0x2b, 0xf7, 0xc8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9a, 0x99, 0x59, 0xbf, 0xae, 0x61, 0x76,
|
||||
0x5e, 0x8d, 0xfd, 0x9d, 0xc7, 0xb2, 0xa0, 0x04, 0x7f, 0xbb, 0x90, 0x38, 0xa3, 0x7e, 0x5e, 0x2c, 0xdf, 0x1c, 0x32,
|
||||
0x72, 0xdd, 0xba, 0x0f, 0x5f, 0x2e, 0x1a, 0xc0, 0x6a, 0xe1, 0x44, 0x05, 0x40, 0x61, 0xb6, 0x93, 0x2b, 0x00, 0x16,
|
||||
0x8a, 0x70, 0x5b, 0xbe, 0x39, 0x1f, 0x89, 0xbd, 0x8f, 0x95, 0xd9, 0xad, 0x4a, 0x11, 0xe6, 0x30, 0xc0, 0xdb, 0x53,
|
||||
0x2a, 0xb9, 0x1b, 0x91, 0x35, 0x4b, 0x6b, 0xe3, 0x17, 0xdf, 0x05, 0x6f, 0xfd, 0xd9, 0x0a, 0xc7, 0x4d, 0x05, 0x6d,
|
||||
0x5e, 0x2d, 0xc9, 0x42, 0x0f, 0x43, 0x96, 0x20, 0xf6, 0x13, 0xd5, 0x35, 0x2d, 0x01, 0x00, 0x00, 0x00, 0xaa, 0xaa,
|
||||
0xaa, 0xaa, 0x54, 0x3d, 0x54, 0x55, 0x57, 0x6d, 0x7e, 0xe2, 0x58, 0xe5, 0x6b, 0x06, 0xb0, 0x3a, 0xd1, 0xcc, 0xda,
|
||||
0xa8, 0x13, 0x71, 0x37, 0x1a, 0x49, 0x4d, 0x00, 0x00, 0x30, 0x32, 0x38, 0x7a, 0x48, 0x1a, 0x77, 0x0f, 0x63, 0xf3,
|
||||
0x88, 0x03, 0x96, 0xed, 0xc5, 0x2c, 0x20, 0xd4, 0xa5, 0x10, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0xcd, 0xcc, 0x84, 0x26, 0x24, 0x60, 0xdd, 0x3b, 0x8b, 0xb9, 0x0a, 0xa7, 0x81, 0xbc, 0x27, 0xda, 0x6d, 0xbc,
|
||||
0x60, 0x76, 0xd7, 0xe7, 0xa3, 0x70, 0x0e, 0x19, 0xb9, 0x6e, 0xdd, 0x87, 0x2f, 0x17, 0xa4, 0x2d, 0x51, 0x76, 0xad,
|
||||
0x02, 0x00, 0xd3, 0xd3, 0x9a, 0x21, 0x0c, 0x03, 0x85, 0xab, 0x50, 0x0b, 0xbf, 0x2d, 0x26, 0x8b, 0x88, 0x87, 0xdd,
|
||||
0xb0, 0xc1, 0xe5, 0x0f, 0x6a, 0xf8, 0xca, 0x23, 0x3a, 0xb0, 0xb8, 0xed, 0x03, 0xb6, 0x19, 0x17, 0xb2, 0xd7, 0xaf,
|
||||
0x25, 0x0f, 0xe8, 0x5d, 0x96, 0x88, 0x6b, 0xd7, 0x7f, 0xe0, 0xb0, 0x41, 0x57, 0xa1, 0x14, 0x1d, 0x55, 0x14, 0x63,
|
||||
0xdb, 0x2a, 0x01, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0xaa, 0xaa, 0x54, 0x3d, 0x54, 0x55, 0x57, 0x6d, 0x7e, 0xe2, 0x58,
|
||||
0xe5, 0x6b, 0x06, 0xb0, 0x3a, 0xd1, 0xcc, 0xda, 0xa8, 0x13, 0x71, 0x37, 0x1a, 0x49, 0x4d, 0x00, 0x00, 0x64, 0x7f,
|
||||
0x44, 0x75, 0xc4, 0x97, 0x37, 0x63, 0x51, 0x19, 0x64, 0xd6, 0x26, 0x62, 0xe4, 0x5c, 0xc4, 0xac, 0xa2, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x67, 0x66, 0xf6, 0x93, 0xf5, 0xd8, 0x74, 0xee, 0xd7, 0xdd,
|
||||
0xc1, 0x95, 0x0c, 0x6d, 0x23, 0x58, 0x1b, 0x30, 0xd1, 0x7c, 0xdd, 0x80, 0xef, 0x51, 0x2b, 0x4b, 0x2b, 0x4c, 0x98,
|
||||
0x97, 0x8e, 0x45, 0xd3, 0x87, 0x93, 0x2f, 0xa7, 0x92, 0xea, 0x68, 0xc2, 0x30, 0x3c, 0x9d, 0xfc, 0xe5, 0x9a, 0xe5,
|
||||
0x63, 0x86, 0xfe, 0xd6, 0x66, 0x52, 0x9b, 0xc9, 0x7e, 0x85, 0xd7, 0x18, 0x5e, 0x6c, 0x19, 0x6d, 0x74, 0x08, 0x36,
|
||||
0xf3, 0xae, 0xf9, 0x4c, 0xa7, 0xa7, 0x41, 0xb5, 0x25, 0x15, 0x62, 0xff, 0xae, 0x96, 0x82, 0xd3, 0x78, 0xf7, 0x79,
|
||||
0x28, 0x91, 0xd6, 0xb7, 0xed, 0x30, 0xea, 0x73, 0x77, 0x25, 0x01, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0xaa, 0xaa, 0x54,
|
||||
0x3d, 0x54, 0x55, 0x57, 0x6d, 0x7e, 0xe2, 0x58, 0xe5, 0x6b, 0x06, 0xb0, 0x3a, 0xd1, 0xcc, 0xda, 0xa8, 0x13, 0x71,
|
||||
0x37, 0x1a, 0x49, 0x4d, 0x00, 0x00, 0xac, 0xba, 0x36, 0xd5, 0x4b, 0x79, 0xf3, 0x04, 0xf5, 0x8c, 0x51, 0xd7, 0x9c,
|
||||
0xc4, 0x42, 0x49, 0x0f, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x33,
|
||||
0x09, 0xd5, 0x70, 0xac, 0x80, 0x04, 0x8f, 0xd9, 0xd8, 0xe8, 0xa6, 0xb4, 0x00, 0x28, 0x46, 0x98, 0xca, 0xc7, 0xd2,
|
||||
0xac, 0x94, 0xc2, 0x39, 0x64, 0xe4, 0xba, 0x75, 0x1f, 0xbe, 0x5c, 0xcf, 0x90, 0x68, 0xf1, 0x6e, 0x4c, 0xca, 0x87,
|
||||
0x8f, 0x21, 0x48, 0xa0, 0x16, 0x8b, 0x99, 0xd9, 0x87, 0x24, 0x9b, 0x40, 0x22, 0xa8, 0x2f, 0x78, 0xa6, 0xa1, 0x66,
|
||||
0xe9, 0x3d, 0x18, 0x20, 0x3d, 0x8f, 0xe7, 0x2a, 0x62, 0x9d, 0x7a, 0x59, 0x9f, 0x19, 0xad, 0x4c, 0x22, 0xf7, 0xd8,
|
||||
0xff, 0x2f, 0xd1, 0x08, 0x62, 0xfa, 0xea, 0x32, 0xde, 0xeb, 0x34, 0xb7, 0x2f, 0xce, 0x59, 0xae, 0x58, 0x5e, 0x01,
|
||||
0x00, 0x00, 0x00, 0xaa, 0xaa, 0xaa, 0xaa, 0x54, 0x3d, 0x54, 0x55, 0x57, 0x6d, 0x7e, 0xe2, 0x58, 0xe5, 0x6b, 0x06,
|
||||
0xb0, 0x3a, 0xd1, 0xcc, 0xda, 0xa8, 0x13, 0x71, 0x37, 0x1a, 0x49, 0x4d, 0x00, 0x00, 0xb5, 0x26, 0x62, 0x47, 0xcf,
|
||||
0x65, 0x84, 0xa1, 0x99, 0xdc, 0x4d, 0x33, 0x06, 0x56, 0x18, 0xe9, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9a, 0x99, 0x05, 0xdc, 0x12, 0x36, 0xab, 0x88, 0x30, 0xba, 0x5f, 0xa0, 0xfb,
|
||||
0x47, 0x07, 0x26, 0x35, 0x41, 0x2f, 0x9d, 0x69, 0x56, 0x4a, 0xe1, 0x1c, 0x32, 0x72, 0xdd, 0xba, 0x0f, 0x5f, 0x2e,
|
||||
0x8a, 0xde, 0x53, 0x36, 0x9b, 0x28, 0xd7, 0xc2, 0x9a, 0xe9, 0x54, 0x8f, 0x12, 0x82, 0x62, 0x7c, 0x80, 0x95, 0xb6,
|
||||
0xe4, 0xb6, 0x95, 0x68, 0x3a, 0x12, 0x91, 0xc6, 0x53, 0x8d, 0xb2, 0x5f, 0x00, 0x98, 0x26, 0x75, 0x9a, 0x48, 0x00,
|
||||
0x22, 0x78, 0xd9, 0x15, 0xe9, 0x48, 0x9c, 0x41, 0x43, 0x00, 0x86, 0x64, 0xcf, 0xef, 0x41, 0xe0, 0x64, 0xc8, 0x06,
|
||||
0xbd, 0xf3, 0x38, 0x14, 0x4d, 0xb4, 0x29, 0x01, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0xaa, 0xaa, 0x54, 0x3d, 0x54, 0x55,
|
||||
0x57, 0x6d, 0x7e, 0xe2, 0x58, 0xe5, 0x6b, 0x06, 0xb0, 0x3a, 0xd1, 0xcc, 0xda, 0xa8, 0x13, 0x71, 0x37, 0x1a, 0x49,
|
||||
0x4d, 0x00, 0x00, 0x03, 0xc6, 0x05, 0x53, 0x9b, 0xa2, 0x22, 0xa8, 0x0c, 0xfa, 0x63, 0x9c, 0xc2, 0x5e, 0x8d, 0x22,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xcd, 0x4c, 0x74, 0x4a, 0xab,
|
||||
0x56, 0x10, 0x49, 0x78, 0xb6, 0xd1, 0x04, 0x5c, 0xb0, 0x7e, 0x50, 0x06, 0xcf, 0xb9, 0xce, 0x34, 0x2b, 0xa5, 0x70,
|
||||
0x0e, 0x19, 0xb9, 0x6e, 0xdd, 0x87, 0x2f, 0x17, 0xa3, 0xd0, 0xde, 0x7e, 0x48, 0x51, 0x64, 0x73, 0x21, 0x48, 0x05,
|
||||
0xf8, 0xb9, 0xaf, 0xa6, 0xc6, 0xfa, 0xf1, 0xaa, 0xea, 0xdc, 0x98, 0xbb, 0xb0, 0x67, 0xa5, 0xd0, 0x60, 0x25, 0x56,
|
||||
0x02, 0x04, 0x13, 0x70, 0x85, 0x7a, 0x7e, 0xf8, 0xf8, 0x6c, 0x77, 0xe5, 0x5b, 0x32, 0x93, 0xdd, 0x77, 0x1c, 0xa8,
|
||||
0x36, 0x1c, 0x19, 0x15, 0xd6, 0x65, 0x8a, 0x9f, 0x83, 0x4a, 0xdf, 0x0f, 0x3c, 0x5c, 0x71, 0x01, 0x00, 0x00, 0x00,
|
||||
0xaa, 0xaa, 0xaa, 0xaa, 0x54, 0x3d, 0x54, 0x55, 0x57, 0x6d, 0x7e, 0xe2, 0x58, 0xe5, 0x6b, 0x06, 0xb0, 0x3a, 0xd1,
|
||||
0xcc, 0xda, 0xa8, 0x13, 0x71, 0x37, 0x1a, 0x49, 0x4d, 0x00, 0x40, 0x58, 0x89, 0xea, 0xfc, 0xd4, 0xce, 0xe7, 0xab,
|
||||
0x47, 0x2a, 0x12, 0x95, 0x93, 0x9d, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x67, 0x66, 0xa3, 0xab, 0x8c, 0xef, 0x89, 0x25, 0x47, 0x52, 0x2b, 0x9e, 0xa5, 0x3b, 0xf4, 0xbe,
|
||||
0xea, 0xe7, 0x2d, 0x6c, 0x9e, 0x81, 0xef, 0x51, 0x2b, 0x4b, 0x2b, 0x4c, 0x98, 0x97, 0x8e, 0x45, 0xce, 0xc3, 0x34,
|
||||
0xb3, 0x70, 0x4e, 0x4d, 0xbe, 0xc5, 0x5a, 0x0c, 0x13, 0x5b, 0xee, 0x07, 0xbf, 0x95, 0x12, 0x7e, 0xed, 0x4d, 0xa4,
|
||||
0x8e, 0xc1, 0x70, 0x34, 0x9e, 0x6a, 0x3b, 0x06, 0xa6, 0x65, 0x0f, 0x2c, 0x93, 0x88, 0xf7, 0xef, 0xc9, 0x9c, 0x0d,
|
||||
0xd3, 0xa8, 0x1f, 0x8b, 0xd7, 0x35, 0xe3, 0xcb, 0xa0, 0x72, 0x39, 0x0b, 0xa8, 0x5a, 0x6f, 0x95, 0xeb, 0x29, 0x88,
|
||||
0x52, 0x3e, 0x01, 0x12, 0x01, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0xaa, 0xaa, 0x54, 0x3d, 0x54, 0x55, 0x57, 0x6d, 0x7e,
|
||||
0xe2, 0x58, 0xe5, 0x6b, 0x06, 0xb0, 0x3a, 0xd1, 0xcc, 0xda, 0xa8, 0x13, 0x71, 0x37, 0x1a, 0x49, 0x4d, 0x00, 0xc0,
|
||||
0x8a, 0x2f, 0x82, 0xda, 0x05, 0x96, 0x7e, 0x40, 0x9e, 0xef, 0x9e, 0xdb, 0x4c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x93, 0x07, 0x17, 0x22, 0x7d, 0xc9, 0xe4,
|
||||
0xa3, 0x4b, 0x66, 0x4e, 0x3b, 0x84, 0x67, 0x34, 0x04, 0xe0, 0xe7, 0x3a, 0xd3, 0xac, 0x94, 0xc2, 0x39, 0x64, 0xe4,
|
||||
0xba, 0x75, 0x1f, 0xbe, 0x5c, 0x0d, 0x88, 0x5f, 0xf8, 0xac, 0x4e, 0xb4, 0x30, 0x5c, 0xc6, 0xff, 0x6c, 0x72, 0xb2,
|
||||
0xcf, 0x0b, 0x70, 0xaf, 0x96, 0x28, 0xa9, 0x31, 0xaf, 0xbc, 0x71, 0x72, 0xf3, 0xf2, 0x77, 0x8e, 0xac, 0x18, 0x59,
|
||||
0xc0, 0x96, 0x6f, 0xa6, 0xde, 0x5d, 0x3b, 0x9f, 0x66, 0x1f, 0x89, 0xf0, 0x8b, 0xe8, 0x62, 0xe1, 0x64, 0x16, 0x30,
|
||||
0xad, 0xff, 0xfd, 0xd9, 0x7f, 0xd8, 0xb0, 0x25, 0x9b, 0x02, 0xa4, 0x00, 0x01, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0xaa,
|
||||
0xaa, 0x54, 0x3d, 0x54, 0x55, 0x57, 0x6d, 0x7e, 0xe2, 0x58, 0xe5, 0x6b, 0x06, 0xb0, 0x3a, 0xd1, 0xcc, 0xda, 0xa8,
|
||||
0x13, 0x71, 0x37, 0x1a, 0x49, 0x4d, 0x00, 0xd0, 0x69, 0x1e, 0xe4, 0x15, 0x78, 0x19, 0x0a, 0xda, 0x1f, 0xdf, 0xc2,
|
||||
0x56, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x9a, 0x59, 0xe1, 0xb5, 0xf5, 0x60, 0x05, 0x8f, 0x81, 0xda, 0xfd, 0xe9, 0x29, 0x5a, 0x76, 0x21, 0x02, 0xf0, 0x73,
|
||||
0x9d, 0x69, 0x56, 0x4a, 0xe1, 0x1c, 0x32, 0x72, 0xdd, 0xba, 0x0f, 0x5f, 0x2e, 0xfd, 0xdf, 0x81, 0x19, 0x3c, 0xad,
|
||||
0xc6, 0x8b, 0x58, 0xfe, 0x51, 0x28, 0xb5, 0xf8, 0xdd, 0x10, 0x20, 0x61, 0x30, 0xb3, 0xb5, 0xf5, 0x76, 0x71, 0xa8,
|
||||
0xc3, 0x57, 0xe4, 0x0c, 0xda, 0x70, 0x11, 0x1e, 0xbd, 0x07, 0x1a, 0xc6, 0xa1, 0x7e, 0x7c, 0xf2, 0x1c, 0xd0, 0x90,
|
||||
0x6d, 0x8f, 0x21, 0x11, 0xde, 0x84, 0x40, 0xb2, 0x19, 0x13, 0x42, 0x9c, 0xf6, 0xc4, 0x72, 0xf5, 0x9e, 0x74, 0xbe,
|
||||
0x50, 0x01, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0xaa, 0xaa, 0x54, 0x3d, 0x54, 0x55, 0x57, 0x6d, 0x7e, 0xe2, 0x58, 0xe5,
|
||||
0x6b, 0x06, 0xb0, 0x3a, 0xd1, 0xcc, 0xda, 0xa8, 0x13, 0x71, 0x37, 0x1a, 0x49, 0x4d, 0x00, 0x30, 0x32, 0x71, 0x23,
|
||||
0x2e, 0xdd, 0x8b, 0xf5, 0xda, 0xc1, 0xf5, 0x60, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xcd, 0x04, 0x3e, 0x2b, 0xd5, 0x66, 0x7c, 0x0c, 0x14, 0xe9, 0xcd,
|
||||
0x52, 0x02, 0x82, 0xbf, 0x10, 0x01, 0xf8, 0xb9, 0xce, 0x34, 0x2b, 0xa5, 0x70, 0x0e, 0x19, 0xb9, 0x6e, 0xdd, 0x87,
|
||||
0x2f, 0x17, 0xc0, 0x5b, 0xf8, 0x94, 0x48, 0x19, 0xd1, 0x27, 0xe0, 0x36, 0x2a, 0x8e, 0xe7, 0x18, 0x70, 0x0f, 0xe1,
|
||||
0x8e, 0xf4, 0x48, 0x72, 0x5c, 0x8e, 0x9c, 0xfb, 0xb9, 0x62, 0xb7, 0xa6, 0x15, 0x84, 0x5e, 0x6f, 0x6b, 0x14, 0xb3,
|
||||
0x43, 0x24, 0xad, 0xe3, 0x9e, 0x76, 0x84, 0x7a, 0x92, 0x8d, 0x04, 0x40, 0x51, 0x73, 0x6b, 0x18, 0xc1, 0x91, 0x25,
|
||||
0x20, 0x40, 0x67, 0x02, 0x0e, 0x72, 0x76, 0x27, 0x6b, 0x01, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0xaa, 0xaa, 0x54, 0x3d,
|
||||
0x54, 0x55, 0x57, 0x6d, 0x7e, 0xe2, 0x58, 0xe5, 0x6b, 0x06, 0xb0, 0x3a, 0xd1, 0xcc, 0xda, 0xa8, 0x13, 0x71, 0x37,
|
||||
0x1a, 0x49, 0x4d, 0x00, 0xa4, 0xd8, 0x1d, 0xa2, 0x5e, 0xa7, 0x37, 0x70, 0xad, 0xd1, 0x9c, 0x02, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x67, 0x76, 0x60,
|
||||
0xee, 0x6c, 0x59, 0x24, 0x5c, 0x74, 0x80, 0x2a, 0x4d, 0x98, 0x95, 0x3e, 0x32, 0x03, 0xe8, 0x2d, 0x6c, 0x9e, 0x81,
|
||||
0xef, 0x51, 0x2b, 0x4b, 0x2b, 0x4c, 0x98, 0x97, 0x8e, 0x45, 0x22, 0x62, 0xe0, 0xd7, 0x4f, 0x07, 0xfe, 0x3a, 0x15,
|
||||
0x87, 0xb6, 0x74, 0x37, 0x21, 0xa4, 0x0a, 0x98, 0x5e, 0x28, 0x12, 0x77, 0xf1, 0x1f, 0x50, 0xd9, 0x8f, 0xf9, 0x40,
|
||||
0x41, 0x6f, 0x0f, 0x4b, 0x87, 0x7d, 0x5e, 0x14, 0x57, 0xf5, 0xe8, 0x74, 0xc4, 0xd4, 0x27, 0xfc, 0x86, 0xd9, 0x56,
|
||||
0x66, 0x17, 0xd6, 0x97, 0xe5, 0x69, 0x2a, 0x6b, 0x03, 0x85, 0x38, 0xda, 0x70, 0xb2, 0xf6, 0xdd, 0x52, 0x01, 0x00,
|
||||
0x00, 0x00, 0xaa, 0xaa, 0xaa, 0xaa, 0x54, 0x3d, 0x54, 0x55, 0x57, 0x6d, 0x7e, 0xe2, 0x58, 0xe5, 0x6b, 0x06, 0xb0,
|
||||
0x3a, 0xd1, 0xcc, 0xda, 0xa8, 0x13, 0x71, 0x37, 0x1a, 0x49, 0x4d, 0x00, 0xac, 0x7f, 0x7a, 0x7f, 0xcc, 0x6b, 0x89,
|
||||
0xc3, 0x0c, 0x8f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x69, 0x13, 0xea, 0xec, 0xb4, 0x88, 0x9c, 0xa2, 0x9b, 0x58, 0x31, 0xcf, 0x1c,
|
||||
0xfe, 0x42, 0x04, 0xe0, 0xe7, 0x3a, 0xd3, 0xac, 0x94, 0xc2, 0x39, 0x64, 0xe4, 0xba, 0x75, 0x1f, 0xbe, 0x5c, 0x4c,
|
||||
0x07, 0x42, 0x14, 0x93, 0xe2, 0x83, 0x93, 0xa3, 0xa9, 0x72, 0x37, 0xa9, 0xb2, 0x58, 0xa7, 0x6a, 0x94, 0x53, 0xb5,
|
||||
0xeb, 0xad, 0x3b, 0x56, 0x46, 0x6b, 0x61, 0xa3, 0x8c, 0x14, 0x56, 0x32, 0xd4, 0x10, 0xf3, 0xf6, 0x64, 0x82, 0xef,
|
||||
0xb0, 0x24, 0xd2, 0xc2, 0x79, 0xde, 0xb0, 0x42, 0x9e, 0x65, 0x05, 0x88, 0x74, 0x2f, 0x8b, 0x58, 0xd5, 0x42, 0x1a,
|
||||
0x06, 0xa3, 0xd4, 0xd1, 0xfc, 0x12, 0x01, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0xaa, 0xaa, 0x54, 0x3d, 0x54, 0x55, 0x57,
|
||||
0x6d, 0x7e, 0xe2, 0x58, 0xe5, 0x6b, 0x06, 0xb0, 0x3a, 0xd1, 0xcc, 0xda, 0xa8, 0x13, 0x71, 0x37, 0x1a, 0x49, 0x4d,
|
||||
0x00, 0xc5, 0x1c, 0xd9, 0xfc, 0x35, 0x0a, 0xad, 0x17, 0xee, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9a, 0x25, 0x9e, 0xe6, 0xbc, 0xaf,
|
||||
0xb1, 0x88, 0x37, 0xd7, 0x97, 0x99, 0x67, 0x0e, 0x7f, 0x21, 0x02, 0xf0, 0x73, 0x9d, 0x69, 0x56, 0x4a, 0xe1, 0x1c,
|
||||
0x32, 0x72, 0xdd, 0xba, 0x0f, 0x5f, 0x2e, 0x5d, 0x53, 0x09, 0xab, 0xc2, 0x58, 0x42, 0x94, 0x15, 0x71, 0x15, 0x1b,
|
||||
0xfa, 0xfb, 0xcd, 0xc6, 0xbc, 0xa4, 0x00, 0x49, 0x74, 0xd3, 0x9c, 0x04, 0x81, 0xd7, 0x09, 0x28, 0x7d, 0x37, 0x37,
|
||||
0x58, 0x8a, 0x94, 0x1a, 0x79, 0x8a, 0x7e, 0x94, 0x29, 0xbd, 0xab, 0x65, 0x5f, 0xc6, 0x94, 0xed, 0xdd, 0x94, 0xc1,
|
||||
0xf1, 0xd8, 0xed, 0x88, 0x80, 0x47, 0x31, 0x52, 0xda, 0x94, 0x30, 0x60, 0xac, 0x0a, 0x01, 0x00, 0x00, 0x00, 0xaa,
|
||||
0xaa, 0xaa, 0xaa, 0x54, 0x3d, 0x54, 0x55, 0x57, 0x6d, 0x7e, 0xe2, 0x58, 0xe5, 0x6b, 0x06, 0xb0, 0x3a, 0xd1, 0xcc,
|
||||
0xda, 0xa8, 0x13, 0x71, 0x37, 0x1a, 0x49, 0x4d, 0x00, 0x83, 0x86, 0xfc, 0xaf, 0x41, 0xb9, 0x0e, 0x8e, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x4d, 0xac, 0x2d, 0x08, 0x88, 0xfd, 0x14, 0x1e, 0x24, 0x78, 0xcc, 0xcc, 0x33, 0x87, 0xbf, 0x10, 0x01,
|
||||
0xf8, 0xb9, 0xce, 0x34, 0x2b, 0xa5, 0x70, 0x0e, 0x19, 0xb9, 0x6e, 0xdd, 0x87, 0x2f, 0x17, 0xbb, 0xc3, 0xc0, 0xea,
|
||||
0xbd, 0x9b, 0xd6, 0x22, 0x75, 0x96, 0x6c, 0xca, 0xc1, 0x2b, 0x45, 0x76, 0x2e, 0x4e, 0x2b, 0xf7, 0xfa, 0x9e, 0x64,
|
||||
0x2d, 0x4b, 0xd8, 0xd9, 0x06, 0x24, 0xa3, 0xce, 0x49, 0x17, 0xd6, 0x83, 0xe8, 0x15, 0xc0, 0xbf, 0x4f, 0xf8, 0x85,
|
||||
0x9d, 0xaf, 0xb6, 0x85, 0x62, 0x31, 0x89, 0x06, 0x10, 0xd3, 0x0a, 0xf1, 0xd5, 0x03, 0x50, 0x2c, 0x1e, 0xf4, 0xa8,
|
||||
0xb6, 0x91, 0x2e, 0x01, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0xaa, 0xaa, 0x54, 0x3d, 0x54, 0x55, 0x57, 0x6d, 0x7e, 0xe2,
|
||||
0x58, 0xe5, 0x6b, 0x06, 0xb0, 0x3a, 0xd1, 0xcc, 0xda, 0xa8, 0x13, 0x71, 0x37, 0x1a, 0x49, 0x4d, 0x40, 0x0c, 0xab,
|
||||
0x80, 0x53, 0x26, 0xc2, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x67, 0x6b, 0xbb, 0x49, 0x36, 0x72, 0x46, 0x68, 0x65,
|
||||
0x6a, 0x65, 0x66, 0x9b, 0x95, 0x3e, 0x32, 0x03, 0xe8, 0x2d, 0x6c, 0x9e, 0x81, 0xef, 0x51, 0x2b, 0x4b, 0x2b, 0x4c,
|
||||
0x98, 0x97, 0x8e, 0x45, 0x80, 0x00, 0x64, 0x53, 0xae, 0xef, 0x99, 0x13, 0xc9, 0x1c, 0x53, 0x45, 0x0c, 0xdc, 0x97,
|
||||
0xd5, 0x80, 0x4b, 0x56, 0x86, 0xa3, 0xbc, 0x78, 0xc4, 0xc2, 0x0c, 0xf7, 0xaf, 0xfd, 0x42, 0xe9, 0x1b, 0x5f, 0x2f,
|
||||
0xa6, 0x4f, 0xa5, 0x53, 0xb5, 0xec, 0x36, 0x50, 0xc6, 0xd1, 0x3f, 0xdf, 0xaf, 0x63, 0x9f, 0x25, 0x1d, 0x40, 0xd2,
|
||||
0xb5, 0x83, 0x24, 0x67, 0x57, 0x4d, 0x0c, 0x7b, 0x8c, 0x90, 0x3d, 0x01, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0xaa, 0xaa,
|
||||
0x54, 0x3d, 0x54, 0x55, 0x57, 0x6d, 0x7e, 0xe2, 0x58, 0xe5, 0x6b, 0x06, 0xb0, 0x3a, 0xd1, 0xcc, 0xda, 0xa8, 0x13,
|
||||
0x71, 0x37, 0x1a, 0x49, 0x4d, 0xc0, 0xfa, 0x49, 0xea, 0x2a, 0x92, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94,
|
||||
0x9d, 0x8c, 0xc4, 0x08, 0x6c, 0x2a, 0x66, 0x32, 0xe3, 0x31, 0x33, 0xcf, 0x1c, 0xfe, 0x42, 0x04, 0xe0, 0xe7, 0x3a,
|
||||
0xd3, 0xac, 0x94, 0xc2, 0x39, 0x64, 0xe4, 0xba, 0x75, 0x1f, 0xbe, 0x5c, 0x57, 0x7e, 0xfd, 0x4b, 0xb2, 0xe8, 0x7d,
|
||||
0x9b, 0x0e, 0x3c, 0x51, 0xa9, 0x15, 0xcb, 0x9e, 0xfa, 0x45, 0x73, 0x63, 0x75, 0xac, 0xb6, 0x70, 0xff, 0xcb, 0x0a,
|
||||
0xb6, 0xd9, 0xd9, 0xf6, 0x7d, 0x5e, 0x31, 0x38, 0x8e, 0xff, 0x0c, 0xba, 0x37, 0xee, 0x71, 0x85, 0x91, 0xa1, 0xc8,
|
||||
0x13, 0x11, 0xc4, 0x7c, 0x0f, 0x6e, 0xca, 0x37, 0x32, 0xdb, 0x2a, 0x5a, 0xf3, 0x69, 0x45, 0x0f, 0x15, 0xe4, 0x1e,
|
||||
0x01, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0xaa, 0xaa, 0x54, 0x3d, 0x54, 0x55, 0x57, 0x6d, 0x7e, 0xe2, 0x58, 0xe5, 0x6b,
|
||||
0x06, 0xb0, 0x3a, 0xd1, 0xcc, 0xda, 0xa8, 0x13, 0x71, 0x37, 0x1a, 0x49, 0x4d, 0xd0, 0xb2, 0x9d, 0x4f, 0x2c, 0x1e,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5a, 0x83, 0xa6, 0xa4, 0x69, 0x0f, 0x33, 0x33, 0x99, 0xf1, 0x98, 0x99,
|
||||
0x67, 0x0e, 0x7f, 0x21, 0x02, 0xf0, 0x73, 0x9d, 0x69, 0x56, 0x4a, 0xe1, 0x1c, 0x32, 0x72, 0xdd, 0xba, 0x0f, 0x5f,
|
||||
0x2e, 0xa0, 0xbc, 0x92, 0xcb, 0x0d, 0xff, 0xd0, 0xea, 0x29, 0x6b, 0x52, 0x84, 0x98, 0xe7, 0xf8, 0xf0, 0xfb, 0x66,
|
||||
0xbe, 0x18, 0xab, 0x4c, 0x1b, 0x71, 0x16, 0xec, 0xb7, 0x81, 0x69, 0x77, 0xeb, 0x57, 0x47, 0xad, 0x0d, 0x3a, 0x20,
|
||||
0x42, 0x92, 0xf1, 0xc1, 0xd3, 0xef, 0x25, 0xf5, 0x26, 0x55, 0xc3, 0x98, 0x49, 0x24, 0xec, 0xbe, 0x30, 0x09, 0xa8,
|
||||
0x07, 0x14, 0x8f, 0xce, 0x6f, 0xdd, 0xa9, 0x71, 0x01, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0xaa, 0xaa, 0x54, 0x3d, 0x54,
|
||||
0x55, 0x57, 0x6d, 0x7e, 0xe2, 0x58, 0xe5, 0x6b, 0x06, 0xb0, 0x3a, 0xd1, 0xcc, 0xda, 0xa8, 0x13, 0x71, 0x37, 0x1a,
|
||||
0x49, 0x4d, 0x30, 0xc2, 0xb2, 0x00, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x85, 0xed, 0x68, 0x0c,
|
||||
0x84, 0x99, 0x99, 0x99, 0xcc, 0x78, 0xcc, 0xcc, 0x33, 0x87, 0xbf, 0x10, 0x01, 0xf8, 0xb9, 0xce, 0x34, 0x2b, 0xa5,
|
||||
0x70, 0x0e, 0x19, 0xb9, 0x6e, 0xdd, 0x87, 0x2f, 0x17, 0x88, 0x7c, 0xf4, 0x83, 0xfd, 0x16, 0xf9, 0xf0, 0x1a, 0xcc,
|
||||
0xc4, 0xea, 0xf5, 0xba, 0x03, 0x19, 0x4a, 0x1b, 0x5d, 0x52, 0xe2, 0xfd, 0x78, 0xb1, 0x3d, 0xd3, 0x03, 0x25, 0x35,
|
||||
0x11, 0x34, 0x47, 0x4d, 0xd6, 0x17, 0x27, 0xbf, 0xde, 0x87, 0x2c, 0xde, 0x46, 0x07, 0xcd, 0x2f, 0xa1, 0x31, 0x26,
|
||||
0xe5, 0x8d, 0x87, 0xe1, 0xda, 0xac, 0xfe, 0x37, 0x97, 0x79, 0x72, 0xc7, 0x3f, 0x28, 0x4a, 0x5e, 0x01, 0x00, 0x00,
|
||||
0x00, 0xaa, 0xaa, 0xaa, 0xaa, 0x54, 0x3d, 0x54, 0x55, 0x57, 0x6d, 0x7e, 0xe2, 0x58, 0xe5, 0x6b, 0x06, 0xb0, 0x3a,
|
||||
0xd1, 0xcc, 0xda, 0xa8, 0x13, 0x71, 0x37, 0x1a, 0x49, 0x4d, 0xe4, 0xc5, 0xbd, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0xf7, 0xec, 0x75, 0x26, 0xcc, 0xcc, 0xcc, 0xcc, 0x65, 0x6a, 0x65, 0x66, 0x9b, 0x95, 0x3e,
|
||||
0x32, 0x03, 0xe8, 0x2d, 0x6c, 0x9e, 0x81, 0xef, 0x51, 0x2b, 0x4b, 0x2b, 0x4c, 0x98, 0x97, 0x8e, 0x45, 0xb3, 0xc4,
|
||||
0x59, 0xb6, 0x35, 0x71, 0xaf, 0xe7, 0x73, 0x4c, 0x03, 0xe2, 0x69, 0x50, 0x19, 0x36, 0x65, 0x43, 0xd5, 0x33, 0x7f,
|
||||
0x31, 0xf1, 0x0e, 0x89, 0xa3, 0x4f, 0x55, 0xdd, 0xf3, 0x67, 0x57, 0xf1, 0xcb, 0xe8, 0x3c, 0x7f, 0x68, 0x6a, 0x29,
|
||||
0xe5, 0x60, 0x35, 0x3e, 0x72, 0x40, 0x3c, 0x8b, 0x39, 0x01, 0xa5, 0x9e, 0x73, 0x99, 0x7f, 0x87, 0x18, 0xb4, 0x68,
|
||||
0xc6, 0xd2, 0x7b, 0xa9, 0x71, 0x01, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0xaa, 0xaa, 0x54, 0x3d, 0x54, 0x55, 0x57, 0x6d,
|
||||
0x7e, 0xe2, 0x58, 0xe5, 0x6b, 0x06, 0xb0, 0x3a, 0xd1, 0xcc, 0xda, 0xa8, 0x13, 0x71, 0x37, 0x1a, 0x49, 0x4d, 0xac,
|
||||
0x68, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xca, 0xff, 0x91, 0x99, 0x65, 0x66, 0x66,
|
||||
0x66, 0x32, 0xe3, 0x31, 0x33, 0xcf, 0x1c, 0xfe, 0x42, 0x04, 0xe0, 0xe7, 0x3a, 0xd3, 0xac, 0x94, 0xc2, 0x39, 0x64,
|
||||
0xe4, 0xba, 0x75, 0x1f, 0xbe, 0x5c, 0x71, 0x02, 0x27, 0x40, 0x1d, 0xe1, 0x11, 0xee, 0x3b, 0xc9, 0x13, 0xe2, 0x90,
|
||||
0x29, 0xf8, 0x0b, 0x70, 0x4b, 0x7b, 0xfa, 0xd2, 0xd6, 0xf5, 0x8f, 0x45, 0xff, 0xc8, 0xc4, 0xc9, 0x4c, 0xf9, 0x5e,
|
||||
0x0e, 0x66, 0x85, 0x5f, 0x88, 0xff, 0xd3, 0xb6, 0xd8, 0x0a, 0x67, 0xd6, 0x91, 0x18, 0x5b, 0xe5, 0xc9, 0xa9, 0xd9,
|
||||
0x55, 0xb4, 0x30, 0xde, 0x83, 0xe5, 0x10, 0x9a, 0x05, 0x55, 0x53, 0xde, 0x55, 0x01, 0x00, 0x00, 0x00, 0xaa, 0xaa,
|
||||
0xaa, 0xaa, 0x54, 0x3d, 0x54, 0x55, 0x57, 0x6d, 0x7e, 0xe2, 0x58, 0xe5, 0x6b, 0x06, 0xb0, 0x3a, 0xd1, 0xcc, 0xda,
|
||||
0xa8, 0x13, 0x71, 0x37, 0x1a, 0x49, 0x4d, 0xd5, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x46, 0xc8, 0xcc, 0xcc, 0x32, 0x33, 0x33, 0x33, 0x99, 0xf1, 0x98, 0x99, 0x67, 0x0e, 0x7f, 0x21, 0x02, 0xf0,
|
||||
0x73, 0x9d, 0x69, 0x56, 0x4a, 0xe1, 0x1c, 0x32, 0x72, 0xdd, 0xba, 0x0f, 0x5f, 0x2e, 0x01, 0x00, 0x00, 0xc0, 0xa9,
|
||||
0xaa, 0xaa, 0x6a, 0x54, 0xd4, 0x53, 0x15, 0x58, 0xd6, 0x6d, 0x37, 0x5a, 0x5b, 0xd4, 0x08, 0xb2, 0xb0, 0x9f, 0xd9,
|
||||
0x2c, 0x08, 0x7b, 0x3b, 0x0c, 0x84, 0x44, 0x6a, 0x08, 0x75, 0x50, 0x67, 0x4d, 0xe0, 0x04, 0xae, 0x38, 0x92, 0x4a,
|
||||
0x99, 0x8b, 0x1e, 0xbb, 0x5f, 0x89, 0x70, 0x45, 0x82, 0x02, 0xe8, 0xe3, 0xe9, 0xea, 0x60, 0x2a, 0xd0, 0xa1, 0xe3,
|
||||
0x59, 0x47, 0x01, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0xaa, 0xaa, 0x54, 0x3d, 0x54, 0x55, 0x57, 0x6d, 0x7e, 0xe2, 0x58,
|
||||
0xe5, 0x6b, 0x06, 0xb0, 0x3a, 0xd1, 0xcc, 0xda, 0xa8, 0x13, 0x71, 0x37, 0x1a, 0x49, 0x4d, 0x03, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x65, 0x66, 0x66, 0xe6, 0x98, 0x99, 0x99, 0x19, 0xcc, 0xa6,
|
||||
0xcb, 0x4c, 0x35, 0x59, 0x9e, 0xba, 0x03, 0xe4, 0x8a, 0xd3, 0x38, 0x17, 0x42, 0x8a, 0xb2, 0xd7, 0x87, 0x03, 0x87,
|
||||
0x5b, 0x26, 0x51, 0x01, 0x00, 0x00, 0x40, 0xff, 0xff, 0xff, 0x3f, 0xff, 0xc4, 0xfe, 0x3f, 0x02, 0x3b, 0xce, 0xfe,
|
||||
0x03, 0x62, 0x39, 0x07, 0x06, 0x62, 0x6b, 0x26, 0xf6, 0x1d, 0x36, 0x5f, 0x7e, 0x3d, 0xf2, 0x56, 0x34, 0x33, 0x33,
|
||||
0x33, 0xcc, 0xcc, 0xcc, 0xcc, 0x65, 0x6a, 0x65, 0x66, 0x9b, 0x95, 0x3e, 0x32, 0x03, 0xe8, 0x2d, 0x6c, 0x9e, 0x81,
|
||||
0xef, 0x51, 0x2b, 0x4b, 0x2b, 0x4c, 0x98, 0x97, 0x8e, 0x45};
|
||||
unsigned int constants_2_len = 11904;
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
72
icicle/appUtils/poseidon/constants/generate_parameters.py
Executable file
72
icicle/appUtils/poseidon/constants/generate_parameters.py
Executable file
@@ -0,0 +1,72 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
# 0.3.7
|
||||
import galois
|
||||
import numpy as np
|
||||
|
||||
# pip install poseidon-hash
|
||||
from poseidon import round_constants as rc, round_numbers as rn
|
||||
|
||||
# Modify these
|
||||
arity = 11
|
||||
p = 0x73EDA753299D7D483339D80809A1D80553BDA402FFFE5BFEFFFFFFFF00000001 # bls12-381
|
||||
# p = 0x12ab655e9a2ca55660b44d1e5c37b00159aa76fed00000010a11800000000001 # bls12-377
|
||||
# p = 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001 # bn254
|
||||
# p = 0x1ae3a4617c510eac63b05c06ca1493b1a22d9f300f5138f1ef3622fba094800170b5d44300000008508c00000000001 # bw6-761
|
||||
prime_bit_len = 255
|
||||
field_bytes = 32
|
||||
|
||||
# leave set to -1 if not sure
|
||||
full_round = -1
|
||||
half_full_round = full_round // 2
|
||||
# leave set to -1 if not sure
|
||||
partial_round = -1
|
||||
|
||||
security_level = 128
|
||||
|
||||
# May speed up Galois significantly. If not sure - set it to None
|
||||
# You can get primitive element fast by using sage
|
||||
# p = ...
|
||||
# F = GF(p)
|
||||
# F.primitive_element()
|
||||
#
|
||||
# primitive_element = None
|
||||
primitive_element = 7 # bls12-381
|
||||
# primitive_element = 22 # bls12-377
|
||||
# primitive_element = 5 # bn254
|
||||
# primitive_element = 15 # bw6-761
|
||||
|
||||
# currently we only support alpha 5, if you need alpha other than 5 - feal free to reach out
|
||||
alpha = 5
|
||||
t = arity + 1
|
||||
|
||||
def flatten(xss):
|
||||
return [x for xs in xss for x in xs]
|
||||
|
||||
if __name__ == "__main__":
|
||||
if full_round == -1 or partial_round == -1:
|
||||
full_round, partial_round, half_full_round = rn.calc_round_numbers(prime_bit_len, security_level, t, alpha, True)
|
||||
print("Half full rounds:", half_full_round)
|
||||
print("Partial rounds:", partial_round)
|
||||
|
||||
print("Loading galois... This might take from several minutes to an hour")
|
||||
field_p = galois.GF(p, 1, verify=False, primitive_element=primitive_element)
|
||||
print("Galois loaded")
|
||||
mds_matrix = rc.mds_matrix_generator(field_p, t)
|
||||
non_opt_rc = rc.calc_round_constants(t, full_round, partial_round, p, field_p, alpha, prime_bit_len)
|
||||
split_rc = [field_p(x.tolist()) for x in np.array_split(non_opt_rc, len(non_opt_rc) / t)]
|
||||
opt_rc = rc.optimized_rc(split_rc, half_full_round, partial_round, mds_matrix)
|
||||
pre_matrix, sparse_matrices = rc.optimized_matrix(mds_matrix, partial_round, field_p)
|
||||
|
||||
sparse_aligned = []
|
||||
for m in sparse_matrices:
|
||||
m = flatten(m.tolist())
|
||||
for j in range(0, t * t, t):
|
||||
sparse_aligned.append(m[j])
|
||||
for j in range(1, t):
|
||||
sparse_aligned.append(m[j])
|
||||
|
||||
with open("constants.bin", "wb") as constants_file:
|
||||
for l in [opt_rc, flatten(mds_matrix), flatten(pre_matrix), sparse_aligned]:
|
||||
for c in l:
|
||||
constants_file.write(int(c).to_bytes(field_bytes, byteorder='little'))
|
||||
175
icicle/appUtils/poseidon/kernels.cu
Normal file
175
icicle/appUtils/poseidon/kernels.cu
Normal file
@@ -0,0 +1,175 @@
|
||||
#include "poseidon.cuh"
|
||||
|
||||
namespace poseidon {
|
||||
template <typename S, int T>
|
||||
__global__ void prepare_poseidon_states(S* states, size_t number_of_states, S domain_tag, bool aligned)
|
||||
{
|
||||
int idx = blockIdx.x * blockDim.x + threadIdx.x;
|
||||
int state_number = idx / T;
|
||||
if (state_number >= number_of_states) { return; }
|
||||
int element_number = idx % T;
|
||||
|
||||
S prepared_element;
|
||||
|
||||
// Domain separation
|
||||
if (element_number == 0) {
|
||||
prepared_element = domain_tag;
|
||||
} else {
|
||||
if (aligned) {
|
||||
prepared_element = states[idx];
|
||||
} else {
|
||||
prepared_element = states[idx - 1];
|
||||
}
|
||||
}
|
||||
|
||||
// We need __syncthreads here if the state is not aligned
|
||||
// because then we need to shift the vector [A, B, 0] -> [D, A, B]
|
||||
if (!aligned) { __syncthreads(); }
|
||||
|
||||
// Store element in state
|
||||
states[idx] = prepared_element;
|
||||
}
|
||||
|
||||
template <typename S>
|
||||
__device__ __forceinline__ S sbox_alpha_five(S element)
|
||||
{
|
||||
S result = S::sqr(element);
|
||||
result = S::sqr(result);
|
||||
return result * element;
|
||||
}
|
||||
|
||||
template <typename S, int T>
|
||||
__device__ S vecs_mul_matrix(S element, S* matrix, int element_number, int vec_number, S* shared_states)
|
||||
{
|
||||
__syncthreads();
|
||||
shared_states[threadIdx.x] = element;
|
||||
__syncthreads();
|
||||
|
||||
typename S::Wide element_wide = S::mul_wide(shared_states[vec_number * T], matrix[element_number]);
|
||||
#pragma unroll
|
||||
for (int i = 1; i < T; i++) {
|
||||
element_wide = element_wide + S::mul_wide(shared_states[vec_number * T + i], matrix[i * T + element_number]);
|
||||
}
|
||||
|
||||
return S::reduce(element_wide);
|
||||
}
|
||||
|
||||
template <typename S, int T>
|
||||
__device__ S full_round(
|
||||
S element,
|
||||
size_t rc_offset,
|
||||
int local_state_number,
|
||||
int element_number,
|
||||
bool multiply_by_mds,
|
||||
bool add_pre_round_constants,
|
||||
bool skip_rc,
|
||||
S* shared_states,
|
||||
const PoseidonConstants<S>& constants)
|
||||
{
|
||||
if (add_pre_round_constants) {
|
||||
element = element + constants.round_constants[rc_offset + element_number];
|
||||
rc_offset += T;
|
||||
}
|
||||
element = sbox_alpha_five(element);
|
||||
if (!skip_rc) { element = element + constants.round_constants[rc_offset + element_number]; }
|
||||
|
||||
// Multiply all the states by mds matrix
|
||||
S* matrix = multiply_by_mds ? constants.mds_matrix : constants.non_sparse_matrix;
|
||||
return vecs_mul_matrix<S, T>(element, matrix, element_number, local_state_number, shared_states);
|
||||
}
|
||||
|
||||
template <typename S, int T>
|
||||
__global__ void full_rounds(
|
||||
S* states, size_t number_of_states, size_t rc_offset, bool first_half, const PoseidonConstants<S> constants)
|
||||
{
|
||||
extern __shared__ S shared_states[];
|
||||
|
||||
int idx = (blockIdx.x * blockDim.x) + threadIdx.x;
|
||||
int state_number = idx / T;
|
||||
if (state_number >= number_of_states) { return; }
|
||||
int local_state_number = threadIdx.x / T;
|
||||
int element_number = idx % T;
|
||||
|
||||
S new_el = states[idx];
|
||||
bool add_pre_round_constants = first_half;
|
||||
for (int i = 0; i < constants.full_rounds_half; i++) {
|
||||
new_el = full_round<S, T>(
|
||||
new_el, rc_offset, local_state_number, element_number, !first_half || (i < (constants.full_rounds_half - 1)),
|
||||
add_pre_round_constants, !first_half && (i == constants.full_rounds_half - 1), shared_states, constants);
|
||||
rc_offset += T;
|
||||
|
||||
if (add_pre_round_constants) {
|
||||
rc_offset += T;
|
||||
add_pre_round_constants = false;
|
||||
}
|
||||
}
|
||||
states[idx] = new_el;
|
||||
}
|
||||
|
||||
template <typename S, int T>
|
||||
__device__ S partial_round(S state[T], size_t rc_offset, int round_number, const PoseidonConstants<S>& constants)
|
||||
{
|
||||
S element = state[0];
|
||||
element = sbox_alpha_five(element);
|
||||
element = element + constants.round_constants[rc_offset];
|
||||
|
||||
S* sparse_matrix = &constants.sparse_matrices[(T * 2 - 1) * round_number];
|
||||
|
||||
typename S::Wide state_0_wide = S::mul_wide(element, sparse_matrix[0]);
|
||||
|
||||
#pragma unroll
|
||||
for (int i = 1; i < T; i++) {
|
||||
state_0_wide = state_0_wide + S::mul_wide(state[i], sparse_matrix[i]);
|
||||
}
|
||||
|
||||
state[0] = S::reduce(state_0_wide);
|
||||
|
||||
#pragma unroll
|
||||
for (int i = 1; i < T; i++) {
|
||||
state[i] = state[i] + (element * sparse_matrix[T + i - 1]);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename S, int T>
|
||||
__global__ void
|
||||
partial_rounds(S* states, size_t number_of_states, size_t rc_offset, const PoseidonConstants<S> constants)
|
||||
{
|
||||
int idx = (blockIdx.x * blockDim.x) + threadIdx.x;
|
||||
if (idx >= number_of_states) { return; }
|
||||
|
||||
S state[T];
|
||||
#pragma unroll
|
||||
for (int i = 0; i < T; i++) {
|
||||
state[i] = states[idx * T + i];
|
||||
}
|
||||
|
||||
for (int i = 0; i < constants.partial_rounds; i++) {
|
||||
partial_round<S, T>(state, rc_offset, i, constants);
|
||||
rc_offset++;
|
||||
}
|
||||
|
||||
#pragma unroll
|
||||
for (int i = 0; i < T; i++) {
|
||||
states[idx * T + i] = state[i];
|
||||
}
|
||||
}
|
||||
|
||||
// These function is just doing copy from the states to the output
|
||||
template <typename S, int T>
|
||||
__global__ void get_hash_results(S* states, size_t number_of_states, S* out)
|
||||
{
|
||||
int idx = (blockIdx.x * blockDim.x) + threadIdx.x;
|
||||
if (idx >= number_of_states) { return; }
|
||||
|
||||
out[idx] = states[idx * T + 1];
|
||||
}
|
||||
|
||||
template <typename S, int T>
|
||||
__global__ void copy_recursive(S* state, size_t number_of_states, S* out)
|
||||
{
|
||||
int idx = (blockIdx.x * blockDim.x) + threadIdx.x;
|
||||
if (idx >= number_of_states) { return; }
|
||||
|
||||
state[(idx / (T - 1) * T) + (idx % (T - 1)) + 1] = out[idx];
|
||||
}
|
||||
} // namespace poseidon
|
||||
@@ -1,269 +1,110 @@
|
||||
#include "../../utils/error_handler.cuh"
|
||||
#include "poseidon.cuh"
|
||||
#include "constants.cu"
|
||||
#include "kernels.cu"
|
||||
|
||||
template <typename S>
|
||||
__global__ void
|
||||
prepare_poseidon_states(S* states, size_t number_of_states, S domain_tag, const PoseidonConfiguration<S> config)
|
||||
{
|
||||
int idx = (blockIdx.x * blockDim.x) + threadIdx.x;
|
||||
int state_number = idx / config.t;
|
||||
if (state_number >= number_of_states) { return; }
|
||||
int element_number = idx % config.t;
|
||||
namespace poseidon {
|
||||
template <typename S, int T>
|
||||
cudaError_t
|
||||
permute_many(S* states, size_t number_of_states, const PoseidonConstants<S>& constants, cudaStream_t& stream)
|
||||
{
|
||||
size_t rc_offset = 0;
|
||||
|
||||
S prepared_element;
|
||||
full_rounds<S, T><<<
|
||||
PKC<T>::number_of_full_blocks(number_of_states), PKC<T>::number_of_threads,
|
||||
sizeof(S) * PKC<T>::hashes_per_block * T, stream>>>(
|
||||
states, number_of_states, rc_offset, FIRST_FULL_ROUNDS, constants);
|
||||
rc_offset += T * (constants.full_rounds_half + 1);
|
||||
|
||||
// Domain separation
|
||||
if (element_number == 0) {
|
||||
prepared_element = domain_tag;
|
||||
} else {
|
||||
prepared_element = states[state_number * config.t + element_number - 1];
|
||||
partial_rounds<S, T>
|
||||
<<<PKC<T>::number_of_singlehash_blocks(number_of_states), PKC<T>::singlehash_block_size, 0, stream>>>(
|
||||
states, number_of_states, rc_offset, constants);
|
||||
rc_offset += constants.partial_rounds;
|
||||
|
||||
full_rounds<S, T><<<
|
||||
PKC<T>::number_of_full_blocks(number_of_states), PKC<T>::number_of_threads,
|
||||
sizeof(S) * PKC<T>::hashes_per_block * T, stream>>>(
|
||||
states, number_of_states, rc_offset, SECOND_FULL_ROUNDS, constants);
|
||||
return CHK_LAST();
|
||||
}
|
||||
|
||||
// Add pre-round constant
|
||||
prepared_element = prepared_element + config.round_constants[element_number];
|
||||
template <typename S, int T>
|
||||
cudaError_t poseidon_hash(
|
||||
S* input, S* output, size_t number_of_states, const PoseidonConstants<S>& constants, const PoseidonConfig& config)
|
||||
{
|
||||
CHK_INIT_IF_RETURN();
|
||||
cudaStream_t& stream = config.ctx.stream;
|
||||
S* states;
|
||||
if (config.input_is_a_state) {
|
||||
states = input;
|
||||
} else {
|
||||
// allocate memory for {number_of_states} states of {t} scalars each
|
||||
CHK_IF_RETURN(cudaMallocAsync(&states, number_of_states * T * sizeof(S), stream))
|
||||
|
||||
// Store element in state
|
||||
states[idx] = prepared_element;
|
||||
}
|
||||
// This is where the input matrix of size Arity x NumberOfBlocks is
|
||||
// padded and copied to device in a T x NumberOfBlocks matrix
|
||||
CHK_IF_RETURN(cudaMemcpy2DAsync(
|
||||
states, T * sizeof(S), // Device pointer and device pitch
|
||||
input, (T - 1) * sizeof(S), // Host pointer and pitch
|
||||
(T - 1) * sizeof(S), number_of_states, // Size of the source matrix (Arity x NumberOfBlocks)
|
||||
cudaMemcpyHostToDevice, stream));
|
||||
}
|
||||
|
||||
template <typename S>
|
||||
__device__ __forceinline__ S sbox_alpha_five(S element)
|
||||
{
|
||||
S result = S::sqr(element);
|
||||
result = S::sqr(result);
|
||||
return result * element;
|
||||
}
|
||||
S* output_device;
|
||||
if (config.are_outputs_on_device) {
|
||||
output_device = output;
|
||||
} else {
|
||||
CHK_IF_RETURN(cudaMallocAsync(&output_device, number_of_states * sizeof(S), stream))
|
||||
}
|
||||
|
||||
template <typename S>
|
||||
__device__ S vecs_mul_matrix(S element, S* matrix, int element_number, int vec_number, int size, S* shared_states)
|
||||
{
|
||||
shared_states[threadIdx.x] = element;
|
||||
__syncthreads();
|
||||
prepare_poseidon_states<S, T>
|
||||
<<<PKC<T>::number_of_full_blocks(number_of_states), PKC<T>::number_of_threads, 0, stream>>>(
|
||||
states, number_of_states, constants.domain_tag, config.aligned);
|
||||
|
||||
element = S::zero();
|
||||
for (int i = 0; i < size; i++) {
|
||||
element = element + (shared_states[vec_number * size + i] * matrix[i * size + element_number]);
|
||||
}
|
||||
__syncthreads();
|
||||
return element;
|
||||
}
|
||||
cudaError_t hash_error = permute_many<S, T>(states, number_of_states, constants, stream);
|
||||
CHK_IF_RETURN(hash_error);
|
||||
|
||||
template <typename S>
|
||||
__device__ S full_round(
|
||||
S element,
|
||||
size_t rc_offset,
|
||||
int local_state_number,
|
||||
int element_number,
|
||||
bool multiply_by_mds,
|
||||
bool add_round_constant,
|
||||
S* shared_states,
|
||||
const PoseidonConfiguration<S> config)
|
||||
{
|
||||
element = sbox_alpha_five(element);
|
||||
if (add_round_constant) { element = element + config.round_constants[rc_offset + element_number]; }
|
||||
get_hash_results<S, T>
|
||||
<<<PKC<T>::number_of_singlehash_blocks(number_of_states), PKC<T>::singlehash_block_size, 0, stream>>>(
|
||||
states, number_of_states, output_device);
|
||||
|
||||
// Multiply all the states by mds matrix
|
||||
S* matrix = multiply_by_mds ? config.mds_matrix : config.non_sparse_matrix;
|
||||
return vecs_mul_matrix(element, matrix, element_number, local_state_number, config.t, shared_states);
|
||||
}
|
||||
if (config.loop_state) {
|
||||
copy_recursive<S, T>
|
||||
<<<PKC<T>::number_of_singlehash_blocks(number_of_states), PKC<T>::singlehash_block_size, 0, stream>>>(
|
||||
states, number_of_states, output_device);
|
||||
}
|
||||
|
||||
// Execute full rounds
|
||||
template <typename S>
|
||||
__global__ void full_rounds(
|
||||
S* states, size_t number_of_states, size_t rc_offset, bool first_half, const PoseidonConfiguration<S> config)
|
||||
{
|
||||
extern __shared__ S shared_states[];
|
||||
if (!config.input_is_a_state) CHK_IF_RETURN(cudaFreeAsync(states, stream));
|
||||
|
||||
int idx = (blockIdx.x * blockDim.x) + threadIdx.x;
|
||||
int state_number = idx / config.t;
|
||||
if (state_number >= number_of_states) { return; }
|
||||
int local_state_number = threadIdx.x / config.t;
|
||||
int element_number = idx % config.t;
|
||||
if (!config.are_outputs_on_device) {
|
||||
CHK_IF_RETURN(
|
||||
cudaMemcpyAsync(output, output_device, number_of_states * sizeof(S), cudaMemcpyDeviceToHost, stream));
|
||||
CHK_IF_RETURN(cudaFreeAsync(output_device, stream));
|
||||
}
|
||||
|
||||
for (int i = 0; i < config.full_rounds_half - 1; i++) {
|
||||
states[idx] =
|
||||
full_round(states[idx], rc_offset, local_state_number, element_number, true, true, shared_states, config);
|
||||
rc_offset += config.t;
|
||||
if (!config.is_async) return CHK_STICKY(cudaStreamSynchronize(stream));
|
||||
return CHK_LAST();
|
||||
}
|
||||
|
||||
states[idx] = full_round(
|
||||
states[idx], rc_offset, local_state_number, element_number, !first_half, first_half, shared_states, config);
|
||||
}
|
||||
|
||||
template <typename S>
|
||||
__device__ S partial_round(S* state, size_t rc_offset, int round_number, const PoseidonConfiguration<S> config)
|
||||
{
|
||||
S element = state[0];
|
||||
element = sbox_alpha_five(element);
|
||||
element = element + config.round_constants[rc_offset];
|
||||
|
||||
S* sparse_matrix = &config.sparse_matrices[(config.t * 2 - 1) * round_number];
|
||||
|
||||
state[0] = element * sparse_matrix[0];
|
||||
for (int i = 1; i < config.t; i++) {
|
||||
state[0] = state[0] + (state[i] * sparse_matrix[i]);
|
||||
extern "C" cudaError_t CONCAT_EXPAND(CURVE, PoseidonHash)(
|
||||
curve_config::scalar_t* input,
|
||||
curve_config::scalar_t* output,
|
||||
int number_of_states,
|
||||
int arity,
|
||||
const PoseidonConstants<curve_config::scalar_t>& constants,
|
||||
PoseidonConfig& config)
|
||||
{
|
||||
switch (arity) {
|
||||
case 2:
|
||||
return poseidon_hash<curve_config::scalar_t, 3>(input, output, number_of_states, constants, config);
|
||||
case 4:
|
||||
return poseidon_hash<curve_config::scalar_t, 5>(input, output, number_of_states, constants, config);
|
||||
case 8:
|
||||
return poseidon_hash<curve_config::scalar_t, 9>(input, output, number_of_states, constants, config);
|
||||
case 11:
|
||||
return poseidon_hash<curve_config::scalar_t, 12>(input, output, number_of_states, constants, config);
|
||||
default:
|
||||
THROW_ICICLE_ERR(IcicleError_t::InvalidArgument, "PoseidonHash: #arity must be one of [2, 4, 8, 11]");
|
||||
}
|
||||
return CHK_LAST();
|
||||
}
|
||||
|
||||
for (int i = 1; i < config.t; i++) {
|
||||
state[i] = state[i] + (element * sparse_matrix[config.t + i - 1]);
|
||||
}
|
||||
}
|
||||
|
||||
// Execute partial rounds
|
||||
template <typename S>
|
||||
__global__ void
|
||||
partial_rounds(S* states, size_t number_of_states, size_t rc_offset, const PoseidonConfiguration<S> config)
|
||||
{
|
||||
int idx = (blockIdx.x * blockDim.x) + threadIdx.x;
|
||||
if (idx >= number_of_states) { return; }
|
||||
|
||||
S* state = &states[idx * config.t];
|
||||
|
||||
for (int i = 0; i < config.partial_rounds; i++) {
|
||||
partial_round(state, rc_offset, i, config);
|
||||
rc_offset++;
|
||||
}
|
||||
}
|
||||
|
||||
// These function is just doing copy from the states to the output
|
||||
template <typename S>
|
||||
__global__ void get_hash_results(S* states, size_t number_of_states, S* out, int t)
|
||||
{
|
||||
int idx = (blockIdx.x * blockDim.x) + threadIdx.x;
|
||||
if (idx >= number_of_states) { return; }
|
||||
|
||||
out[idx] = states[idx * t + 1];
|
||||
}
|
||||
|
||||
template <typename S>
|
||||
__host__ cudaError_t
|
||||
Poseidon<S>::hash_blocks(const S* inp, size_t blocks, S* out, HashType hash_type, cudaStream_t stream)
|
||||
{
|
||||
CHK_INIT_IF_RETURN();
|
||||
|
||||
S* states;
|
||||
|
||||
// allocate memory for {blocks} states of {t} scalars each
|
||||
CHK_IF_RETURN(cudaMallocAsync(&states, blocks * this->t * sizeof(S), stream));
|
||||
|
||||
// This is where the input matrix of size Arity x NumberOfBlocks is
|
||||
// padded and copied to device in a T x NumberOfBlocks matrix
|
||||
CHK_IF_RETURN(cudaMemcpy2DAsync(
|
||||
states, this->t * sizeof(S), // Device pointer and device pitch
|
||||
inp, (this->t - 1) * sizeof(S), // Host pointer and pitch
|
||||
(this->t - 1) * sizeof(S), blocks, // Size of the source matrix (Arity x NumberOfBlocks)
|
||||
cudaMemcpyHostToDevice, stream));
|
||||
|
||||
size_t rc_offset = 0;
|
||||
|
||||
// The logic behind this is that 1 thread only works on 1 element
|
||||
// We have {t} elements in each state, and {blocks} states total
|
||||
int number_of_threads = (256 / this->t) * this->t;
|
||||
int hashes_per_block = number_of_threads / this->t;
|
||||
int total_number_of_threads = blocks * this->t;
|
||||
int number_of_blocks =
|
||||
total_number_of_threads / number_of_threads + static_cast<bool>(total_number_of_threads % number_of_threads);
|
||||
|
||||
// The partial rounds operates on the whole state, so we define
|
||||
// the parallelism params for processing a single hash preimage per thread
|
||||
int singlehash_block_size = 128;
|
||||
int number_of_singlehash_blocks = blocks / singlehash_block_size + static_cast<bool>(blocks % singlehash_block_size);
|
||||
|
||||
// Pick the domain_tag accordinaly
|
||||
S domain_tag;
|
||||
switch (hash_type) {
|
||||
case HashType::ConstInputLen:
|
||||
domain_tag = this->const_input_no_pad_domain_tag;
|
||||
break;
|
||||
|
||||
case HashType::MerkleTree:
|
||||
domain_tag = this->tree_domain_tag;
|
||||
}
|
||||
|
||||
#if !defined(__CUDA_ARCH__) && defined(DEBUG)
|
||||
auto start_time = std::chrono::high_resolution_clock::now();
|
||||
#endif
|
||||
|
||||
// Domain separation and adding pre-round constants
|
||||
prepare_poseidon_states<<<number_of_blocks, number_of_threads, 0, stream>>>(states, blocks, domain_tag, this->config);
|
||||
rc_offset += this->t;
|
||||
|
||||
#if !defined(__CUDA_ARCH__) && defined(DEBUG)
|
||||
CHK_IF_RETURN(cudaStreamSynchronize(stream));
|
||||
std::cout << "Domain separation: " << rc_offset << std::endl;
|
||||
// print_buffer_from_cuda<S>(states, blocks * this->t);
|
||||
|
||||
auto end_time = std::chrono::high_resolution_clock::now();
|
||||
auto elapsed_time = std::chrono::duration_cast<std::chrono::milliseconds>(end_time - start_time);
|
||||
std::cout << "Elapsed time: " << elapsed_time.count() << " ms" << std::endl;
|
||||
start_time = std::chrono::high_resolution_clock::now();
|
||||
#endif
|
||||
|
||||
// execute half full rounds
|
||||
full_rounds<<<number_of_blocks, number_of_threads, this->t * sizeof(S) * hashes_per_block, stream>>>(
|
||||
states, blocks, rc_offset, true, this->config);
|
||||
rc_offset += this->t * this->config.full_rounds_half;
|
||||
|
||||
#if !defined(__CUDA_ARCH__) && defined(DEBUG)
|
||||
CHK_IF_RETURN(cudaStreamSynchronize(stream));
|
||||
std::cout << "Full rounds 1. RCOFFSET: " << rc_offset << std::endl;
|
||||
// print_buffer_from_cuda<S>(states, blocks * this->t);
|
||||
|
||||
end_time = std::chrono::high_resolution_clock::now();
|
||||
elapsed_time = std::chrono::duration_cast<std::chrono::milliseconds>(end_time - start_time);
|
||||
std::cout << "Elapsed time: " << elapsed_time.count() << " ms" << std::endl;
|
||||
start_time = std::chrono::high_resolution_clock::now();
|
||||
#endif
|
||||
|
||||
// execute partial rounds
|
||||
partial_rounds<<<number_of_singlehash_blocks, singlehash_block_size, 0, stream>>>(
|
||||
states, blocks, rc_offset, this->config);
|
||||
rc_offset += this->config.partial_rounds;
|
||||
|
||||
#if !defined(__CUDA_ARCH__) && defined(DEBUG)
|
||||
CHK_IF_RETURN(cudaStreamSynchronize(stream));
|
||||
std::cout << "Partial rounds. RCOFFSET: " << rc_offset << std::endl;
|
||||
// print_buffer_from_cuda<S>(states, blocks * this->t);
|
||||
|
||||
end_time = std::chrono::high_resolution_clock::now();
|
||||
elapsed_time = std::chrono::duration_cast<std::chrono::milliseconds>(end_time - start_time);
|
||||
std::cout << "Elapsed time: " << elapsed_time.count() << " ms" << std::endl;
|
||||
start_time = std::chrono::high_resolution_clock::now();
|
||||
#endif
|
||||
|
||||
// execute half full rounds
|
||||
full_rounds<<<number_of_blocks, number_of_threads, this->t * sizeof(S) * hashes_per_block, stream>>>(
|
||||
states, blocks, rc_offset, false, this->config);
|
||||
|
||||
#if !defined(__CUDA_ARCH__) && defined(DEBUG)
|
||||
CHK_IF_RETURN(cudaStreamSynchronize(stream));
|
||||
std::cout << "Full rounds 2. RCOFFSET: " << rc_offset << std::endl;
|
||||
// print_buffer_from_cuda<S>(states, blocks * this->t);
|
||||
end_time = std::chrono::high_resolution_clock::now();
|
||||
elapsed_time = std::chrono::duration_cast<std::chrono::milliseconds>(end_time - start_time);
|
||||
std::cout << "Elapsed time: " << elapsed_time.count() << " ms" << std::endl;
|
||||
start_time = std::chrono::high_resolution_clock::now();
|
||||
#endif
|
||||
|
||||
// get output
|
||||
S* out_device;
|
||||
CHK_IF_RETURN(cudaMalloc(&out_device, blocks * sizeof(S)));
|
||||
get_hash_results<<<number_of_singlehash_blocks, singlehash_block_size, 0, stream>>>(
|
||||
states, blocks, out_device, this->config.t);
|
||||
|
||||
#if !defined(__CUDA_ARCH__) && defined(DEBUG)
|
||||
CHK_IF_RETURN(cudaStreamSynchronize(stream));
|
||||
std::cout << "Get hash results" << std::endl;
|
||||
end_time = std::chrono::high_resolution_clock::now();
|
||||
elapsed_time = std::chrono::duration_cast<std::chrono::milliseconds>(end_time - start_time);
|
||||
std::cout << "Elapsed time: " << elapsed_time.count() << " ms" << std::endl;
|
||||
#endif
|
||||
CHK_IF_RETURN(cudaMemcpyAsync(out, out_device, blocks * sizeof(S), cudaMemcpyDeviceToHost, stream));
|
||||
CHK_IF_RETURN(cudaFreeAsync(out_device, stream));
|
||||
CHK_IF_RETURN(cudaFreeAsync(states, stream));
|
||||
|
||||
#if !defined(__CUDA_ARCH__) && defined(DEBUG)
|
||||
CHK_IF_RETURN(cudaDeviceReset());
|
||||
#endif
|
||||
return CHK_LAST();
|
||||
}
|
||||
} // namespace poseidon
|
||||
@@ -1,157 +1,140 @@
|
||||
#pragma once
|
||||
#include "constants.cuh"
|
||||
#ifndef POSEIDON_H
|
||||
#define POSEIDON_H
|
||||
|
||||
#if !defined(__CUDA_ARCH__) && defined(DEBUG)
|
||||
#include <chrono>
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <cstdint>
|
||||
#include <stdexcept>
|
||||
#include "utils/device_context.cuh"
|
||||
#include "curves/curve_config.cuh"
|
||||
#include "utils/error_handler.cuh"
|
||||
#include "utils/utils.h"
|
||||
|
||||
template <typename S>
|
||||
__host__ void print_buffer_from_cuda(S* device_ptr, size_t size, size_t t)
|
||||
{
|
||||
S* buffer = static_cast<S*>(malloc(size * sizeof(S)));
|
||||
CHK_LOG(checudaMemcpy(buffer, device_ptr, size * sizeof(S), cudaMemcpyDeviceToHost));
|
||||
/**
|
||||
* @namespace poseidon
|
||||
* Implementation of the [Poseidon hash function](https://eprint.iacr.org/2019/458.pdf)
|
||||
* Specifically, the optimized [Filecoin version](https://spec.filecoin.io/algorithms/crypto/poseidon/)
|
||||
*/
|
||||
namespace poseidon {
|
||||
#define FIRST_FULL_ROUNDS true
|
||||
#define SECOND_FULL_ROUNDS false
|
||||
|
||||
std::cout << "Start print" << std::endl;
|
||||
for (int i = 0; i < size / t; i++) {
|
||||
std::cout << "State #" << i << std::endl;
|
||||
for (int j = 0; j < t; j++) {
|
||||
std::cout << buffer[i * t + j] << std::endl;
|
||||
}
|
||||
std::cout << std::endl;
|
||||
}
|
||||
std::cout << std::endl;
|
||||
free(buffer);
|
||||
}
|
||||
#endif
|
||||
/**
|
||||
* For most of the Poseidon configurations this is the case
|
||||
* To-do: Add support for different full rounds numbers
|
||||
*/
|
||||
const int FULL_ROUNDS_DEFAULT = 4;
|
||||
|
||||
#ifdef DEBUG
|
||||
template <typename S>
|
||||
__device__ void print_scalar(S element, int data)
|
||||
{
|
||||
printf(
|
||||
"D# %d, T# %d: 0x%08x%08x%08x%08x%08x%08x%08x%08x\n", data, threadIdx.x, element.limbs_storage.limbs[0],
|
||||
element.limbs_storage.limbs[1], element.limbs_storage.limbs[2], element.limbs_storage.limbs[3],
|
||||
element.limbs_storage.limbs[4], element.limbs_storage.limbs[5], element.limbs_storage.limbs[6],
|
||||
element.limbs_storage.limbs[7]);
|
||||
}
|
||||
#endif
|
||||
|
||||
template <typename S>
|
||||
struct PoseidonConfiguration {
|
||||
uint32_t partial_rounds, full_rounds_half, t;
|
||||
S *round_constants, *mds_matrix, *non_sparse_matrix, *sparse_matrices;
|
||||
};
|
||||
|
||||
template <typename S>
|
||||
class Poseidon
|
||||
{
|
||||
public:
|
||||
uint32_t t;
|
||||
PoseidonConfiguration<S> config;
|
||||
|
||||
enum HashType {
|
||||
ConstInputLen,
|
||||
MerkleTree,
|
||||
/**
|
||||
* @struct PoseidonConstants
|
||||
* This constants are enough to define a Poseidon instantce
|
||||
* @param round_constants A pointer to round constants allocated on the device
|
||||
* @param mds_matrix A pointer to an mds matrix allocated on the device
|
||||
* @param non_sparse_matrix A pointer to non sparse matrix allocated on the device
|
||||
* @param sparse_matrices A pointer to sparse matrices allocated on the device
|
||||
*/
|
||||
template <typename S>
|
||||
struct PoseidonConstants {
|
||||
int arity;
|
||||
int partial_rounds;
|
||||
int full_rounds_half;
|
||||
S* round_constants = nullptr;
|
||||
S* mds_matrix = nullptr;
|
||||
S* non_sparse_matrix = nullptr;
|
||||
S* sparse_matrices = nullptr;
|
||||
S domain_tag;
|
||||
};
|
||||
|
||||
Poseidon(const uint32_t arity, cudaStream_t stream)
|
||||
/**
|
||||
* @class PoseidonKernelsConfiguration
|
||||
* Describes the logic of deriving CUDA kernels parameters
|
||||
* such as the number of threads and the number of blocks
|
||||
*/
|
||||
template <int T>
|
||||
class PoseidonKernelsConfiguration
|
||||
{
|
||||
t = arity + 1;
|
||||
this->config.t = t;
|
||||
this->stream = stream;
|
||||
public:
|
||||
// The logic behind this is that 1 thread only works on 1 element
|
||||
// We have {T} elements in each state, and {number_of_states} states total
|
||||
static const int number_of_threads = 256 / T * T;
|
||||
|
||||
// Pre-calculate domain tags
|
||||
// Domain tags will vary for different applications of Poseidon
|
||||
uint32_t tree_domain_tag_value = 1;
|
||||
tree_domain_tag_value = (tree_domain_tag_value << arity) - tree_domain_tag_value;
|
||||
tree_domain_tag = S::from(tree_domain_tag_value);
|
||||
// The partial rounds operates on the whole state, so we define
|
||||
// the parallelism params for processing a single hash preimage per thread
|
||||
static const int singlehash_block_size = 128;
|
||||
|
||||
const_input_no_pad_domain_tag = S::one();
|
||||
static const int hashes_per_block = number_of_threads / T;
|
||||
|
||||
// TO-DO: implement binary shifts for scalar type
|
||||
// const_input_no_pad_domain_tag = S::one() << 64;
|
||||
// const_input_no_pad_domain_tag *= S::from(arity);
|
||||
static int number_of_full_blocks(size_t number_of_states)
|
||||
{
|
||||
int total_number_of_threads = number_of_states * T;
|
||||
return total_number_of_threads / number_of_threads +
|
||||
static_cast<bool>(total_number_of_threads % number_of_threads);
|
||||
}
|
||||
|
||||
this->config.full_rounds_half = FULL_ROUNDS_DEFAULT;
|
||||
this->config.partial_rounds = partial_rounds_number_from_arity(arity);
|
||||
static int number_of_singlehash_blocks(size_t number_of_states)
|
||||
{
|
||||
return number_of_states / singlehash_block_size + static_cast<bool>(number_of_states % singlehash_block_size);
|
||||
}
|
||||
};
|
||||
|
||||
uint32_t round_constants_len = t * this->config.full_rounds_half * 2 + this->config.partial_rounds;
|
||||
uint32_t mds_matrix_len = t * t;
|
||||
uint32_t sparse_matrices_len = (t * 2 - 1) * this->config.partial_rounds;
|
||||
template <int T>
|
||||
using PKC = PoseidonKernelsConfiguration<T>;
|
||||
|
||||
// All the constants are stored in a single file
|
||||
S* constants = load_constants<S>(arity);
|
||||
/**
|
||||
* @struct NTTConfig
|
||||
* Struct that encodes various Poseidon parameters.
|
||||
*/
|
||||
struct PoseidonConfig {
|
||||
device_context::DeviceContext ctx; /**< Details related to the device such as its id and stream id. */
|
||||
bool are_inputs_on_device; /**< True if inputs are on device and false if they're on host. Default value: false. */
|
||||
bool are_outputs_on_device; /**< If true, output is preserved on device, otherwise on host. Default value: false. */
|
||||
bool input_is_a_state; /**< If true, input is considered to be a states vector, holding the preimages
|
||||
* in aligned or not aligned format. Memory under the input pointer will be used for states
|
||||
* If false, fresh states memory will be allocated and input will be copied into it */
|
||||
bool aligned; /**< If true - input should be already aligned for poseidon permutation.
|
||||
* Aligned format: [0, A, B, 0, C, D, ...] (as you might get by using loop_state)
|
||||
* not aligned format: [A, B, 0, C, D, 0, ...] (as you might get from cudaMemcpy2D) */
|
||||
bool loop_state; /**< If true, hash results will also be copied in the input pointer in aligned format */
|
||||
bool is_async; /**< Whether to run the Poseidon asynchronously. If set to `true`, the poseidon_hash function will be
|
||||
* non-blocking and you'd need to synchronize it explicitly by running
|
||||
* `cudaStreamSynchronize` or `cudaDeviceSynchronize`. If set to false, the poseidon_hash
|
||||
* function will block the current CPU thread. */
|
||||
};
|
||||
|
||||
S* mds_offset = constants + round_constants_len;
|
||||
S* non_sparse_offset = mds_offset + mds_matrix_len;
|
||||
S* sparse_matrices_offset = non_sparse_offset + mds_matrix_len;
|
||||
|
||||
#if !defined(__CUDA_ARCH__) && defined(DEBUG)
|
||||
std::cout << "P: " << this->config.partial_rounds << " F: " << this->config.full_rounds_half << std::endl;
|
||||
#endif
|
||||
|
||||
// Create streams for copying constants
|
||||
cudaStream_t stream_copy_round_constants, stream_copy_mds_matrix, stream_copy_non_sparse,
|
||||
stream_copy_sparse_matrices;
|
||||
cudaStreamCreate(&stream_copy_round_constants);
|
||||
cudaStreamCreate(&stream_copy_mds_matrix);
|
||||
cudaStreamCreate(&stream_copy_non_sparse);
|
||||
cudaStreamCreate(&stream_copy_sparse_matrices);
|
||||
|
||||
// Create events for copying constants
|
||||
cudaEvent_t event_copied_round_constants, event_copy_mds_matrix, event_copy_non_sparse, event_copy_sparse_matrices;
|
||||
cudaEventCreateWithFlags(&event_copied_round_constants, cudaEventDisableTiming);
|
||||
cudaEventCreateWithFlags(&event_copy_mds_matrix, cudaEventDisableTiming);
|
||||
cudaEventCreateWithFlags(&event_copy_non_sparse, cudaEventDisableTiming);
|
||||
cudaEventCreateWithFlags(&event_copy_sparse_matrices, cudaEventDisableTiming);
|
||||
|
||||
// Malloc memory for copying constants
|
||||
cudaMallocAsync(&this->config.round_constants, sizeof(S) * round_constants_len, stream_copy_round_constants);
|
||||
cudaMallocAsync(&this->config.mds_matrix, sizeof(S) * mds_matrix_len, stream_copy_mds_matrix);
|
||||
cudaMallocAsync(&this->config.non_sparse_matrix, sizeof(S) * mds_matrix_len, stream_copy_non_sparse);
|
||||
cudaMallocAsync(&this->config.sparse_matrices, sizeof(S) * sparse_matrices_len, stream_copy_sparse_matrices);
|
||||
|
||||
// Copy constants
|
||||
cudaMemcpyAsync(
|
||||
this->config.round_constants, constants, sizeof(S) * round_constants_len, cudaMemcpyHostToDevice,
|
||||
stream_copy_round_constants);
|
||||
cudaMemcpyAsync(
|
||||
this->config.mds_matrix, mds_offset, sizeof(S) * mds_matrix_len, cudaMemcpyHostToDevice, stream_copy_mds_matrix);
|
||||
cudaMemcpyAsync(
|
||||
this->config.non_sparse_matrix, non_sparse_offset, sizeof(S) * mds_matrix_len, cudaMemcpyHostToDevice,
|
||||
stream_copy_non_sparse);
|
||||
cudaMemcpyAsync(
|
||||
this->config.sparse_matrices, sparse_matrices_offset, sizeof(S) * sparse_matrices_len, cudaMemcpyHostToDevice,
|
||||
stream_copy_sparse_matrices);
|
||||
|
||||
// Record finished copying event for streams
|
||||
cudaEventRecord(event_copied_round_constants, stream_copy_round_constants);
|
||||
cudaEventRecord(event_copy_mds_matrix, stream_copy_mds_matrix);
|
||||
cudaEventRecord(event_copy_non_sparse, stream_copy_non_sparse);
|
||||
cudaEventRecord(event_copy_sparse_matrices, stream_copy_sparse_matrices);
|
||||
|
||||
// Main stream waits for copying to finish
|
||||
cudaStreamWaitEvent(stream, event_copied_round_constants);
|
||||
cudaStreamWaitEvent(stream, event_copy_mds_matrix);
|
||||
cudaStreamWaitEvent(stream, event_copy_non_sparse);
|
||||
cudaStreamWaitEvent(stream, event_copy_sparse_matrices);
|
||||
template <typename S>
|
||||
PoseidonConfig default_poseidon_config(int t)
|
||||
{
|
||||
device_context::DeviceContext ctx = device_context::get_default_device_context();
|
||||
PoseidonConfig config = {
|
||||
ctx, // ctx
|
||||
false, // are_inputes_on_device
|
||||
false, // are_outputs_on_device
|
||||
false, // input_is_a_state
|
||||
false, // aligned
|
||||
false, // loop_state
|
||||
false, // is_async
|
||||
};
|
||||
return config;
|
||||
}
|
||||
|
||||
~Poseidon()
|
||||
{
|
||||
cudaFreeAsync(this->config.round_constants, this->stream);
|
||||
cudaFreeAsync(this->config.mds_matrix, this->stream);
|
||||
cudaFreeAsync(this->config.non_sparse_matrix, this->stream);
|
||||
cudaFreeAsync(this->config.sparse_matrices, this->stream);
|
||||
}
|
||||
/**
|
||||
* Loads pre-calculated optimized constants, moves them to the device
|
||||
*/
|
||||
template <typename S>
|
||||
cudaError_t init_optimized_poseidon_constants(device_context::DeviceContext& ctx, PoseidonConstants<S>* constants);
|
||||
|
||||
// Hash multiple preimages in parallel
|
||||
cudaError_t hash_blocks(const S* inp, size_t blocks, S* out, HashType hash_type, cudaStream_t stream);
|
||||
/**
|
||||
* Compute the poseidon hash over a sequence of preimages.
|
||||
* Takes {number_of_states * (T-1)} elements of input and computes {number_of_states} hash images
|
||||
* @param T size of the poseidon state, should be equal to {arity + 1}
|
||||
* @param input a pointer to the input data. May be allocated on device or on host, regulated
|
||||
* by the config. May point to a string of preimages or a string of states filled with preimages.
|
||||
* @param output a pointer to the output data. May be allocated on device or on host, regulated
|
||||
* by the config. Must be at least of size [number_of_states](@ref number_of_states)
|
||||
* @param number_of_states number of input blocks of size T-1 (arity)
|
||||
*/
|
||||
template <typename S, int T>
|
||||
cudaError_t poseidon_hash(
|
||||
S* input, S* output, size_t number_of_states, const PoseidonConstants<S>& constants, const PoseidonConfig& config);
|
||||
} // namespace poseidon
|
||||
|
||||
private:
|
||||
S tree_domain_tag, const_input_no_pad_domain_tag;
|
||||
cudaStream_t stream;
|
||||
};
|
||||
#endif
|
||||
@@ -1,67 +1,57 @@
|
||||
// TODO: add to gtest or remove
|
||||
// #define DEBUG
|
||||
|
||||
#include "../../curves/bls12_381/curve_config.cuh"
|
||||
#include "../../curves/bls12_381/poseidon.cu"
|
||||
#define CURVE_ID 2
|
||||
#include "../../curves/curve_config.cuh"
|
||||
#include "../../utils/device_context.cuh"
|
||||
#include "poseidon.cu"
|
||||
|
||||
#ifndef __CUDA_ARCH__
|
||||
#include <cassert>
|
||||
#include <chrono>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
|
||||
using namespace poseidon;
|
||||
using namespace curve_config;
|
||||
|
||||
#define A 2
|
||||
#define T (A + 1)
|
||||
|
||||
#define START_TIMER(timer) auto timer##_start = std::chrono::high_resolution_clock::now();
|
||||
#define END_TIMER(timer, msg) \
|
||||
printf("%s: %.0f ms\n", msg, FpMilliseconds(std::chrono::high_resolution_clock::now() - timer##_start).count());
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
using FpMilliseconds = std::chrono::duration<float, std::chrono::milliseconds::period>;
|
||||
using FpMicroseconds = std::chrono::duration<float, std::chrono::microseconds::period>;
|
||||
|
||||
const int arity = 2;
|
||||
const int t = arity + 1;
|
||||
// Load poseidon constants
|
||||
START_TIMER(timer_const);
|
||||
device_context::DeviceContext ctx = device_context::get_default_device_context();
|
||||
PoseidonConstants<scalar_t> constants;
|
||||
init_optimized_poseidon_constants<scalar_t>(A, ctx, &constants);
|
||||
END_TIMER(timer_const, "Load poseidon constants");
|
||||
|
||||
cudaStream_t stream;
|
||||
cudaStreamCreate(&stream);
|
||||
|
||||
cudaEvent_t start_event, end_event;
|
||||
cudaEventCreate(&start_event);
|
||||
cudaEventCreate(&end_event);
|
||||
cudaEventRecord(start_event, stream);
|
||||
auto start_time1 = std::chrono::high_resolution_clock::now();
|
||||
Poseidon<BLS12_381::scalar_t> poseidon(arity, stream);
|
||||
|
||||
auto end_time1 = std::chrono::high_resolution_clock::now();
|
||||
auto elapsed_time1 = std::chrono::duration_cast<std::chrono::microseconds>(end_time1 - start_time1);
|
||||
printf("Elapsed time poseidon: %.0f us\n", FpMicroseconds(elapsed_time1).count());
|
||||
|
||||
int number_of_blocks = 1024;
|
||||
|
||||
BLS12_381::scalar_t input = BLS12_381::scalar_t::zero();
|
||||
BLS12_381::scalar_t* in_ptr =
|
||||
static_cast<BLS12_381::scalar_t*>(malloc(number_of_blocks * arity * sizeof(BLS12_381::scalar_t)));
|
||||
for (uint32_t i = 0; i < number_of_blocks * arity; i++) {
|
||||
START_TIMER(allocation_timer);
|
||||
// Prepare input data of [0, 1, 2 ... (number_of_blocks * arity) - 1]
|
||||
int number_of_blocks = argc > 1 ? 1 << atoi(argv[1]) : 1024;
|
||||
scalar_t input = scalar_t::zero();
|
||||
scalar_t* in_ptr = static_cast<scalar_t*>(malloc(number_of_blocks * A * sizeof(scalar_t)));
|
||||
for (uint32_t i = 0; i < number_of_blocks * A; i++) {
|
||||
in_ptr[i] = input;
|
||||
input = input + BLS12_381::scalar_t::one();
|
||||
input = input + scalar_t::one();
|
||||
}
|
||||
std::cout << std::endl;
|
||||
END_TIMER(allocation_timer, "Allocate mem and fill input");
|
||||
|
||||
BLS12_381::scalar_t* out_ptr =
|
||||
static_cast<BLS12_381::scalar_t*>(malloc(number_of_blocks * sizeof(BLS12_381::scalar_t)));
|
||||
scalar_t* out_ptr = static_cast<scalar_t*>(malloc(number_of_blocks * sizeof(scalar_t)));
|
||||
|
||||
auto start_time = std::chrono::high_resolution_clock::now();
|
||||
START_TIMER(poseidon_timer);
|
||||
PoseidonConfig config = default_poseidon_config<scalar_t>(T);
|
||||
poseidon_hash<curve_config::scalar_t, T>(in_ptr, out_ptr, number_of_blocks, constants, config);
|
||||
END_TIMER(poseidon_timer, "Poseidon")
|
||||
|
||||
poseidon.hash_blocks(in_ptr, number_of_blocks, out_ptr, Poseidon<BLS12_381::scalar_t>::HashType::MerkleTree, stream);
|
||||
auto end_time = std::chrono::high_resolution_clock::now();
|
||||
auto elapsed_time = std::chrono::duration_cast<std::chrono::microseconds>(end_time - start_time);
|
||||
printf("Elapsed time hash: %.0f us\n", FpMicroseconds(elapsed_time).count());
|
||||
cudaEventRecord(end_event, stream);
|
||||
cudaEventSynchronize(end_event);
|
||||
|
||||
float elapsedTime;
|
||||
cudaEventElapsedTime(&elapsedTime, start_event, end_event);
|
||||
printf("Elapsed time: %8.3f ms\n", elapsedTime);
|
||||
|
||||
cudaEventDestroy(start_event);
|
||||
cudaEventDestroy(end_event);
|
||||
|
||||
BLS12_381::scalar_t expected[1024] = {
|
||||
scalar_t expected[1024] = {
|
||||
{2583881727, 773864502, 2634393245, 2801510707, 49275233, 1939738585, 1584833899, 962922711},
|
||||
{1482052501, 2945755510, 2790332687, 3994795689, 2690398473, 2055226187, 3927265331, 526041267},
|
||||
{908959580, 3968357170, 168369822, 4279251122, 172491869, 1810633943, 1108167336, 461319268},
|
||||
@@ -1087,14 +1077,15 @@ int main(int argc, char* argv[])
|
||||
{3906397586, 3290474371, 1675512984, 4178526889, 2952985253, 3592646253, 1572272369, 508740262},
|
||||
{4126315652, 3786312147, 3699923125, 3674356834, 1459586774, 373249965, 2436297855, 1091365949}};
|
||||
|
||||
for (int i = 0; i < number_of_blocks; i++) {
|
||||
assert((out_ptr[i] == expected[i]));
|
||||
|
||||
if (number_of_blocks == 1024) {
|
||||
for (int i = 0; i < number_of_blocks; i++) {
|
||||
#ifdef DEBUG
|
||||
std::cout << out_ptr[i] << std::endl;
|
||||
std::cout << out_ptr[i] << std::endl;
|
||||
#endif
|
||||
assert((out_ptr[i] == expected[i]));
|
||||
}
|
||||
printf("Expected output matches\n");
|
||||
}
|
||||
printf("Expected output matches\n");
|
||||
|
||||
free(in_ptr);
|
||||
free(out_ptr);
|
||||
1
icicle/appUtils/tree/.gitignore
vendored
Normal file
1
icicle/appUtils/tree/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
test_merkle
|
||||
3
icicle/appUtils/tree/Makefile
Normal file
3
icicle/appUtils/tree/Makefile
Normal file
@@ -0,0 +1,3 @@
|
||||
test_merkle:
|
||||
nvcc -o test_merkle -I. -I../.. test.cu
|
||||
./test_merkle
|
||||
280
icicle/appUtils/tree/merkle.cu
Normal file
280
icicle/appUtils/tree/merkle.cu
Normal file
@@ -0,0 +1,280 @@
|
||||
#include "merkle.cuh"
|
||||
|
||||
namespace merkle {
|
||||
/// Flattens the tree digests and sum them up to get
|
||||
/// the memory needed to contain all the digests
|
||||
template <typename S>
|
||||
size_t get_digests_len(uint32_t height, uint32_t arity)
|
||||
{
|
||||
size_t digests_len = 0;
|
||||
size_t row_length = 1;
|
||||
for (int i = 1; i < height; i++) {
|
||||
digests_len += row_length;
|
||||
row_length *= arity;
|
||||
}
|
||||
|
||||
return digests_len;
|
||||
}
|
||||
|
||||
/// Constructs merkle subtree without parallelization
|
||||
/// The digests are aligned sequentially per row
|
||||
/// Example:
|
||||
///
|
||||
/// Big tree:
|
||||
///
|
||||
/// 1
|
||||
/// / \
|
||||
/// 2 3
|
||||
/// / \ / \
|
||||
/// 4 5 6 7
|
||||
///
|
||||
/// Subtree 1 Subtree 2
|
||||
/// 2 3
|
||||
/// / \ / \
|
||||
/// 4 5 6 7
|
||||
///
|
||||
/// Digests array for subtree 1:
|
||||
/// [4 5 . . 2 . .]
|
||||
/// | | |
|
||||
/// ----- V
|
||||
/// | Segment (offset = 4, subtree_idx = 0)
|
||||
/// v
|
||||
/// Segment (offset = 0, subtree_idx = 0)
|
||||
///
|
||||
/// Digests array for subtree 2:
|
||||
/// [. . 6 7 . 3 .]
|
||||
/// | |
|
||||
/// -----
|
||||
/// |
|
||||
/// v
|
||||
/// Segment (offset = 0, subtree_idx = 1)
|
||||
///
|
||||
/// Total digests array:
|
||||
/// [4 5 6 7 2 3 .]
|
||||
template <typename S, int T>
|
||||
cudaError_t build_merkle_subtree(
|
||||
S* state,
|
||||
S* digests,
|
||||
size_t subtree_idx,
|
||||
size_t subtree_height,
|
||||
S* big_tree_digests,
|
||||
size_t start_segment_size,
|
||||
size_t start_segment_offset,
|
||||
int keep_rows,
|
||||
const PoseidonConstants<S>& poseidon,
|
||||
cudaStream_t& stream)
|
||||
{
|
||||
int arity = T - 1;
|
||||
|
||||
PoseidonConfig config = default_poseidon_config<S>(T);
|
||||
config.are_inputs_on_device = true;
|
||||
config.are_outputs_on_device = true;
|
||||
config.input_is_a_state = true;
|
||||
config.loop_state = true;
|
||||
config.ctx.stream = stream;
|
||||
|
||||
size_t leaves_size = pow(arity, subtree_height - 1);
|
||||
uint32_t number_of_blocks = leaves_size / arity;
|
||||
size_t segment_size = start_segment_size;
|
||||
size_t segment_offset = start_segment_offset;
|
||||
|
||||
while (number_of_blocks > 0) {
|
||||
cudaError_t poseidon_res = poseidon_hash<S, T>(state, digests, number_of_blocks, poseidon, config);
|
||||
CHK_IF_RETURN(poseidon_res);
|
||||
|
||||
if (!keep_rows || subtree_height <= keep_rows + 1) {
|
||||
S* digests_with_offset = big_tree_digests + segment_offset + subtree_idx * number_of_blocks;
|
||||
CHK_IF_RETURN(
|
||||
cudaMemcpyAsync(digests_with_offset, digests, number_of_blocks * sizeof(S), cudaMemcpyDeviceToHost, stream));
|
||||
segment_offset += segment_size;
|
||||
}
|
||||
|
||||
segment_size /= arity;
|
||||
subtree_height--;
|
||||
number_of_blocks /= arity;
|
||||
config.aligned = true;
|
||||
}
|
||||
|
||||
return CHK_LAST();
|
||||
}
|
||||
|
||||
template <typename S, int T>
|
||||
cudaError_t build_merkle_tree(
|
||||
const S* leaves,
|
||||
S* digests,
|
||||
uint32_t height,
|
||||
const poseidon::PoseidonConstants<S>& poseidon,
|
||||
const TreeBuilderConfig& config)
|
||||
{
|
||||
CHK_INIT_IF_RETURN();
|
||||
cudaStream_t& stream = config.ctx.stream;
|
||||
|
||||
int arity = T - 1;
|
||||
uint32_t number_of_leaves = pow(arity, (height - 1));
|
||||
|
||||
// This will determine how much splitting do we need to do
|
||||
// `number_of_streams` subtrees should fit in the device
|
||||
// This means each subtree should fit in `STREAM_CHUNK_SIZE` memory
|
||||
uint32_t number_of_subtrees = 1;
|
||||
uint32_t subtree_height = height;
|
||||
uint32_t subtree_leaves_size = pow(arity, height - 1);
|
||||
uint32_t subtree_state_size = subtree_leaves_size / arity * T;
|
||||
uint32_t subtree_digests_size = get_digests_len<S>(subtree_height, arity);
|
||||
size_t subtree_memory_required = sizeof(S) * (subtree_state_size + subtree_digests_size);
|
||||
while (subtree_memory_required > STREAM_CHUNK_SIZE) {
|
||||
number_of_subtrees *= arity;
|
||||
subtree_height--;
|
||||
subtree_leaves_size /= arity;
|
||||
subtree_state_size = subtree_leaves_size / arity * T;
|
||||
subtree_digests_size = subtree_state_size / arity;
|
||||
subtree_memory_required = sizeof(S) * (subtree_state_size + subtree_digests_size);
|
||||
}
|
||||
int cap_height = height - subtree_height + 1;
|
||||
size_t caps_len = pow(arity, cap_height - 1);
|
||||
|
||||
size_t available_memory, _total_memory;
|
||||
CHK_IF_RETURN(cudaMemGetInfo(&available_memory, &_total_memory));
|
||||
available_memory -= GIGA / 8; // Leave 128 MB
|
||||
|
||||
// We can effectively parallelize memory copy with streams
|
||||
// as long as they don't operate on more than `STREAM_CHUNK_SIZE` bytes
|
||||
const size_t number_of_streams = std::min((uint32_t)(available_memory / STREAM_CHUNK_SIZE), number_of_subtrees);
|
||||
cudaStream_t* streams = static_cast<cudaStream_t*>(malloc(sizeof(cudaStream_t) * number_of_streams));
|
||||
for (size_t i = 0; i < number_of_streams; i++) {
|
||||
CHK_IF_RETURN(cudaStreamCreate(&streams[i]));
|
||||
}
|
||||
|
||||
#if !defined(__CUDA_ARCH__) && defined(MERKLE_DEBUG)
|
||||
std::cout << "Available memory = " << available_memory / 1024 / 1024 << " MB" << std::endl;
|
||||
std::cout << "Number of streams = " << number_of_streams << std::endl;
|
||||
std::cout << "Number of subtrees = " << number_of_subtrees << std::endl;
|
||||
std::cout << "Height of a subtree = " << subtree_height << std::endl;
|
||||
std::cout << "Cutoff height = " << height - subtree_height + 1 << std::endl;
|
||||
std::cout << "Number of leaves in a subtree = " << subtree_leaves_size << std::endl;
|
||||
std::cout << "State of a subtree = " << subtree_state_size << std::endl;
|
||||
std::cout << "Digest elements for a subtree = " << get_digests_len<S>(subtree_height, arity) << std::endl;
|
||||
std::cout << "Size of 1 subtree states = " << subtree_state_size * sizeof(S) / 1024 / 1024 << " MB" << std::endl;
|
||||
std::cout << "Size of 1 subtree digests = " << subtree_digests_size * sizeof(S) / 1024 / 1024 << " MB" << std::endl;
|
||||
#endif
|
||||
|
||||
// Allocate memory for the leaves and digests
|
||||
// These are shared by streams in a pool
|
||||
S *states_ptr, *digests_ptr;
|
||||
CHK_IF_RETURN(cudaMallocAsync(&states_ptr, subtree_state_size * number_of_streams * sizeof(S), stream))
|
||||
CHK_IF_RETURN(cudaMallocAsync(&digests_ptr, subtree_digests_size * number_of_streams * sizeof(S), stream))
|
||||
// Wait for these allocations to finish
|
||||
CHK_IF_RETURN(cudaStreamSynchronize(stream));
|
||||
|
||||
bool caps_mode = config.keep_rows && config.keep_rows < cap_height;
|
||||
S* caps;
|
||||
if (caps_mode) { caps = static_cast<S*>(malloc(caps_len * sizeof(S))); }
|
||||
|
||||
for (size_t subtree_idx = 0; subtree_idx < number_of_subtrees; subtree_idx++) {
|
||||
size_t stream_idx = subtree_idx % number_of_streams;
|
||||
cudaStream_t subtree_stream = streams[stream_idx];
|
||||
|
||||
const S* subtree_leaves = leaves + subtree_idx * subtree_leaves_size;
|
||||
S* subtree_state = states_ptr + stream_idx * subtree_state_size;
|
||||
S* subtree_digests = digests_ptr + stream_idx * subtree_digests_size;
|
||||
|
||||
// Copy the first level from RAM / device to device
|
||||
// The pitch property of cudaMemcpy2D resolves shape differences
|
||||
CHK_IF_RETURN(cudaMemcpy2DAsync(
|
||||
subtree_state, T * sizeof(S), // Device pointer and device pitch
|
||||
subtree_leaves, arity * sizeof(S), // Host pointer and pitch
|
||||
arity * sizeof(S), // Size of the source matrix (Arity)
|
||||
subtree_leaves_size / arity, // Size of the source matrix (Number of blocks)
|
||||
config.are_inputs_on_device ? cudaMemcpyDeviceToDevice : cudaMemcpyHostToDevice, subtree_stream));
|
||||
|
||||
int subtree_keep_rows = 0;
|
||||
if (config.keep_rows) {
|
||||
int diff = config.keep_rows - cap_height + 1;
|
||||
subtree_keep_rows = diff <= 0 ? 1 : diff;
|
||||
}
|
||||
size_t start_segment_size = number_of_leaves / arity;
|
||||
cudaError_t subtree_result = build_merkle_subtree<S, T>(
|
||||
subtree_state, // state
|
||||
subtree_digests, // digests
|
||||
subtree_idx, // subtree_idx
|
||||
subtree_height, // subtree_height
|
||||
caps_mode ? caps : digests, // big_tree_digests
|
||||
start_segment_size, // start_segment_size
|
||||
0, // start_segment_offset
|
||||
subtree_keep_rows, // keep_rows
|
||||
poseidon, // hash
|
||||
subtree_stream // stream
|
||||
);
|
||||
CHK_IF_RETURN(subtree_result);
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < number_of_streams; i++) {
|
||||
CHK_IF_RETURN(cudaStreamSynchronize(streams[i]));
|
||||
}
|
||||
|
||||
// Finish the top-level tree if any
|
||||
if (cap_height > 1) {
|
||||
size_t start_segment_size = caps_len / arity;
|
||||
size_t start_segment_offset = 0;
|
||||
if (!caps_mode) {
|
||||
size_t layer_size = pow(arity, config.keep_rows - 1);
|
||||
for (int i = 0; i < config.keep_rows - cap_height + 1; i++) {
|
||||
start_segment_offset += layer_size;
|
||||
layer_size /= arity;
|
||||
}
|
||||
}
|
||||
CHK_IF_RETURN(cudaMemcpy2DAsync(
|
||||
states_ptr, T * sizeof(S), caps_mode ? caps : (digests + start_segment_offset - caps_len), arity * sizeof(S),
|
||||
arity * sizeof(S),
|
||||
caps_len / arity, // Size of the source
|
||||
cudaMemcpyHostToDevice, stream)); // Direction and stream
|
||||
|
||||
cudaError_t top_tree_result = build_merkle_subtree<S, T>(
|
||||
states_ptr, // state
|
||||
digests_ptr, // digests
|
||||
0, // subtree_idx
|
||||
cap_height, // subtree_height
|
||||
digests, // big_tree_digests
|
||||
start_segment_size, // start_segment_size
|
||||
start_segment_offset, // start_segment_offset
|
||||
config.keep_rows, // keep_rows
|
||||
poseidon, // hash
|
||||
stream // stream
|
||||
);
|
||||
CHK_IF_RETURN(top_tree_result);
|
||||
if (caps_mode) { free(caps); }
|
||||
}
|
||||
|
||||
CHK_IF_RETURN(cudaFreeAsync(states_ptr, stream));
|
||||
CHK_IF_RETURN(cudaFreeAsync(digests_ptr, stream));
|
||||
if (!config.is_async) return CHK_STICKY(cudaStreamSynchronize(stream));
|
||||
for (size_t i = 0; i < number_of_streams; i++) {
|
||||
CHK_IF_RETURN(cudaStreamSynchronize(streams[i]));
|
||||
CHK_IF_RETURN(cudaStreamDestroy(streams[i]));
|
||||
}
|
||||
free(streams);
|
||||
return CHK_LAST();
|
||||
}
|
||||
|
||||
extern "C" cudaError_t CONCAT_EXPAND(CURVE, BuildPoseidonMerkleTree)(
|
||||
const curve_config::scalar_t* leaves,
|
||||
curve_config::scalar_t* digests,
|
||||
uint32_t height,
|
||||
int arity,
|
||||
PoseidonConstants<curve_config::scalar_t>& constants,
|
||||
TreeBuilderConfig& config)
|
||||
{
|
||||
switch (arity) {
|
||||
case 2:
|
||||
return build_merkle_tree<curve_config::scalar_t, 3>(leaves, digests, height, constants, config);
|
||||
case 4:
|
||||
return build_merkle_tree<curve_config::scalar_t, 5>(leaves, digests, height, constants, config);
|
||||
case 8:
|
||||
return build_merkle_tree<curve_config::scalar_t, 9>(leaves, digests, height, constants, config);
|
||||
case 11:
|
||||
return build_merkle_tree<curve_config::scalar_t, 12>(leaves, digests, height, constants, config);
|
||||
default:
|
||||
THROW_ICICLE_ERR(IcicleError_t::InvalidArgument, "BuildPoseidonMerkleTree: #arity must be one of [2, 4, 8, 11]");
|
||||
}
|
||||
return CHK_LAST();
|
||||
}
|
||||
} // namespace merkle
|
||||
75
icicle/appUtils/tree/merkle.cuh
Normal file
75
icicle/appUtils/tree/merkle.cuh
Normal file
@@ -0,0 +1,75 @@
|
||||
#pragma once
|
||||
#ifndef MERKLE_H
|
||||
#define MERKLE_H
|
||||
|
||||
#include "utils/device_context.cuh"
|
||||
#include "utils/error_handler.cuh"
|
||||
#include "utils/utils.h"
|
||||
#include "appUtils/poseidon/poseidon.cuh"
|
||||
|
||||
#include <iostream>
|
||||
#include <math.h>
|
||||
|
||||
using namespace poseidon;
|
||||
|
||||
/**
|
||||
* @namespace merkle
|
||||
* Implementation of the [Poseidon](@ref poseidon) [Merkle tree](https://en.wikipedia.org/wiki/Merkle_tree) builder,
|
||||
* parallelized for the use on GPU
|
||||
*/
|
||||
namespace merkle {
|
||||
static constexpr size_t GIGA = 1024 * 1024 * 1024;
|
||||
|
||||
/// Bytes per stream
|
||||
static constexpr size_t STREAM_CHUNK_SIZE = 1024 * 1024 * 1024;
|
||||
|
||||
/**
|
||||
* @struct TreeBuilderConfig
|
||||
* Struct that encodes various Tree builder parameters.
|
||||
*/
|
||||
struct TreeBuilderConfig {
|
||||
device_context::DeviceContext ctx; /**< Details related to the device such as its id and stream id. */
|
||||
int keep_rows; /**< How many rows of the Merkle tree rows should be written to output. '0' means all of them */
|
||||
bool are_inputs_on_device; /**< True if inputs are on device and false if they're on host. Default value: false. */
|
||||
bool is_async; /**< Whether to run the tree builder asynchronously. If set to `true`, the build_merkle_tree
|
||||
* function will be non-blocking and you'd need to synchronize it explicitly by running
|
||||
* `cudaStreamSynchronize` or `cudaDeviceSynchronize`. If set to false, the
|
||||
* function will block the current CPU thread. */
|
||||
};
|
||||
|
||||
template <typename S>
|
||||
TreeBuilderConfig default_merkle_config()
|
||||
{
|
||||
device_context::DeviceContext ctx = device_context::get_default_device_context();
|
||||
TreeBuilderConfig config = {
|
||||
ctx, // ctx
|
||||
0, // keep_rows
|
||||
false, // are_inputes_on_device
|
||||
false, // is_async
|
||||
};
|
||||
return config;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the Poseidon Merkle tree
|
||||
*
|
||||
* @param leaves a pointer to the leaves layer. May be allocated on device or on host, regulated by the config
|
||||
* Expected to have arity ^ (height - 1) elements
|
||||
* @param digests a pointer to the digests storage. May only be allocated on the host
|
||||
* Expected to have `sum(arity ^ (i)) for i in [0..height-1]`
|
||||
* @param height the height of the merkle tree
|
||||
* # Algorithm
|
||||
* The function will split large tree into many subtrees of size that will fit `STREAM_CHUNK_SIZE`.
|
||||
* Each subtree is build in it's own stream (there is a maximum number of streams)
|
||||
* After all subtrees are constructed - the function will combine the resulting sub-digests into the final top-tree
|
||||
*/
|
||||
template <typename S, int T>
|
||||
cudaError_t build_merkle_tree(
|
||||
const S* leaves,
|
||||
S* digests,
|
||||
uint32_t height,
|
||||
const PoseidonConstants<S>& poseidon,
|
||||
const TreeBuilderConfig& config);
|
||||
} // namespace merkle
|
||||
|
||||
#endif
|
||||
232
icicle/appUtils/tree/test.cu
Normal file
232
icicle/appUtils/tree/test.cu
Normal file
@@ -0,0 +1,232 @@
|
||||
// #define DEBUG
|
||||
#define MERKLE_DEBUG
|
||||
|
||||
#define CURVE_ID 2
|
||||
#include "../../curves/curve_config.cuh"
|
||||
#include "../poseidon/poseidon.cu"
|
||||
#include "merkle.cu"
|
||||
|
||||
#ifndef __CUDA_ARCH__
|
||||
#include <cassert>
|
||||
#include <chrono>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <math.h>
|
||||
|
||||
using namespace poseidon;
|
||||
using namespace merkle;
|
||||
using namespace curve_config;
|
||||
using FpMilliseconds = std::chrono::duration<float, std::chrono::milliseconds::period>;
|
||||
|
||||
// Arity
|
||||
#define A 2
|
||||
#define T (A + 1)
|
||||
|
||||
#define START_TIMER(timer) auto timer##_start = std::chrono::high_resolution_clock::now();
|
||||
#define END_TIMER(timer, msg) \
|
||||
printf("%s: %.0f ms\n", msg, FpMilliseconds(std::chrono::high_resolution_clock::now() - timer##_start).count());
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
// Load poseidon constants
|
||||
START_TIMER(timer_const);
|
||||
device_context::DeviceContext ctx = device_context::get_default_device_context();
|
||||
PoseidonConstants<scalar_t> constants;
|
||||
init_optimized_poseidon_constants<scalar_t>(A, ctx, &constants);
|
||||
END_TIMER(timer_const, "Load poseidon constants");
|
||||
|
||||
/// Tree of height N and arity A contains \sum{A^i} for i in 0..N-1 elements
|
||||
uint32_t tree_height = argc > 1 ? atoi(argv[1]) : 28;
|
||||
uint32_t number_of_leaves = pow(A, (tree_height - 1));
|
||||
|
||||
/// Use keep_rows to specify how many rows do you want to store
|
||||
int keep_rows = argc > 2 ? atoi(argv[2]) : 7;
|
||||
size_t digests_len = get_digests_len<scalar_t>(keep_rows + 1, A);
|
||||
|
||||
/// Fill leaves with scalars [0, 1, ... 2^{tree_height - 1} - 1]
|
||||
START_TIMER(timer_allocation);
|
||||
scalar_t input = scalar_t::zero();
|
||||
size_t leaves_mem = number_of_leaves * sizeof(scalar_t);
|
||||
scalar_t* leaves = static_cast<scalar_t*>(malloc(leaves_mem));
|
||||
for (uint32_t i = 0; i < number_of_leaves; i++) {
|
||||
leaves[i] = input;
|
||||
input = input + scalar_t::one();
|
||||
}
|
||||
END_TIMER(timer_allocation, "Allocated memory for leaves: ");
|
||||
|
||||
/// Allocate memory for digests of {keep_rows} rows of a tree
|
||||
START_TIMER(timer_digests);
|
||||
size_t digests_mem = digests_len * sizeof(scalar_t);
|
||||
scalar_t* digests = static_cast<scalar_t*>(malloc(digests_mem));
|
||||
END_TIMER(timer_digests, "Allocated memory for digests");
|
||||
|
||||
std::cout << "Memory for leaves = " << leaves_mem / 1024 / 1024 << " MB; " << leaves_mem / 1024 / 1024 / 1024 << " GB"
|
||||
<< std::endl;
|
||||
std::cout << "Number of leaves = " << number_of_leaves << std::endl;
|
||||
std::cout << "Memory for digests = " << digests_mem / 1024 / 1024 << " MB; " << digests_mem / 1024 / 1024 / 1024
|
||||
<< " GB" << std::endl;
|
||||
std::cout << "Number of digest elements = " << digests_len << std::endl;
|
||||
|
||||
std::cout << "Total RAM consumption = " << (digests_mem + leaves_mem) / 1024 / 1024 << " MB; "
|
||||
<< (digests_mem + leaves_mem) / 1024 / 1024 / 1024 << " GB" << std::endl;
|
||||
|
||||
TreeBuilderConfig config = default_merkle_config<scalar_t>();
|
||||
config.keep_rows = keep_rows;
|
||||
START_TIMER(timer_merkle);
|
||||
build_merkle_tree<scalar_t, T>(leaves, digests, tree_height, constants, config);
|
||||
END_TIMER(timer_merkle, "Merkle tree built: ")
|
||||
|
||||
// Use this to generate test vectors
|
||||
// for (int i = 0; i < digests_len; i++) {
|
||||
// std::cout << "{";
|
||||
// for (int j = 0; j < 8; j++) {
|
||||
// std::cout << ((uint32_t*)&digests[i].limbs_storage)[j];
|
||||
// if (j != 7) { std::cout << ", "; }
|
||||
// }
|
||||
// std::cout << "}," << std::endl;
|
||||
// }
|
||||
|
||||
/// These scalars are digests of top-7 rows of a Merkle tree.
|
||||
/// Arity = 2, Tree height = 28, keep_rows = 7
|
||||
/// They are aligned in the following format:
|
||||
/// L-7 L-6 L-5 L-4 L-3 L-2 L-1
|
||||
/// [0..63, 64..95, 96..111, 112..119, 120..123, 124..125, 126]
|
||||
scalar_t expected[127] = {
|
||||
{4014678573, 3239475319, 2314653449, 2957861895, 184634791, 3566699115, 1715234110, 445241356},
|
||||
{3505304837, 808365954, 2275962701, 1423516791, 1541423175, 1724600321, 226400287, 1785337258},
|
||||
{2768067495, 1388793239, 3997362411, 3464112194, 1973409933, 3681177968, 369038929, 472214073},
|
||||
{3654540770, 1469373240, 3282216438, 3185867716, 967978472, 1078033214, 78178652, 1830882032},
|
||||
{490654422, 2525841937, 626688402, 392783721, 58008344, 2145494226, 3242212931, 274501152},
|
||||
{3208477883, 3672804666, 239023996, 4035696816, 3265333325, 958951383, 181142437, 1239596452},
|
||||
{2969561146, 4232772549, 1556993315, 1662679755, 2909096842, 1439765953, 667526824, 31896728},
|
||||
{270711313, 12541629, 3347448212, 371567649, 1759208919, 1723057963, 674629473, 1013019629},
|
||||
{3017193939, 2312231485, 3737856857, 1313052851, 1196989094, 1495382607, 1023560618, 191925995},
|
||||
{293080341, 2290910595, 1543157595, 1127848979, 1815285163, 1706352673, 992727722, 591498292},
|
||||
{3549180392, 2881478531, 2660879925, 1033961139, 2665175480, 2168183735, 3470220482, 849297604},
|
||||
{2676239944, 3976356940, 2496525380, 1062384559, 686775848, 383379365, 3327679344, 1084443735},
|
||||
{1971496657, 3091116054, 3681796601, 1418643776, 3299382044, 3857762866, 3539539764, 1326628306},
|
||||
{630542774, 2408275928, 345917713, 687603493, 3754703591, 3550860419, 2083130565, 770159409},
|
||||
{870888363, 224377249, 3918057820, 3375742820, 2591003788, 2510070975, 3414099060, 340676877},
|
||||
{1875497580, 1000647891, 3811413293, 2001777831, 2253197473, 2328265571, 3906271342, 325320055},
|
||||
{1211415187, 488575334, 500057698, 3280169717, 3697121693, 1438922954, 931086076, 620808784},
|
||||
{1983293587, 2168562163, 3150824284, 3953229527, 436705204, 778341443, 3005081450, 615688285},
|
||||
{8576698, 3039838264, 671609957, 2809480667, 1620765047, 2117613498, 845941068, 455906025},
|
||||
{3906454348, 552283113, 645539850, 1316302434, 475485784, 2970197657, 274367582, 652809948},
|
||||
{1495892355, 1668646651, 14573046, 3197699206, 1489087180, 3696907100, 1481991676, 1713300937},
|
||||
{3908239800, 3651019608, 3657128408, 1619241101, 2332486430, 639066149, 2163145035, 1704519873},
|
||||
{601030174, 3024947211, 2825655316, 3863514365, 749861326, 2966866369, 3590896102, 1433089687},
|
||||
{2395125120, 2965783566, 2438173617, 591910928, 2454874264, 961201946, 3519059509, 1507770765},
|
||||
{4191182380, 3986691529, 626672198, 248199214, 2672873299, 1206537516, 4088647235, 643192311},
|
||||
{117373628, 2684708015, 1169533105, 4189512228, 39193015, 2348829360, 1044287150, 1200318263},
|
||||
{1641468310, 184141241, 1225984447, 3048243879, 3866424998, 3590741693, 2510098016, 274097253},
|
||||
{805243263, 2967911161, 448427804, 518401505, 404860884, 1593480904, 2843784918, 1217394583},
|
||||
{1068910868, 4126158631, 3428265735, 1108050638, 1809164812, 2970655045, 916421502, 271686161},
|
||||
{2733872014, 3489610640, 2253010322, 2061408208, 209418696, 317724116, 2610511126, 777106564},
|
||||
{922170442, 222695863, 4287857383, 1811357610, 3378048665, 339334666, 156256237, 1016584661},
|
||||
{2369411073, 3974740601, 3926942050, 1092836585, 2755312327, 492736530, 1777994166, 1608349307},
|
||||
{3791947957, 2178563469, 2708512205, 2104428978, 4281280169, 3158413195, 3714473637, 1932398193},
|
||||
{447850698, 872401916, 1547172058, 1242046677, 1896710579, 1137814221, 1602961798, 1571006781},
|
||||
{3469094617, 1395163063, 1061899259, 4059174800, 2083256644, 1034754354, 941298869, 416224305},
|
||||
{3468873946, 3282426941, 497353671, 953582605, 1587266512, 1740183981, 671088260, 1875939615},
|
||||
{3123987458, 2866544187, 2718390509, 359710965, 259964033, 4177846877, 740787103, 1674220305},
|
||||
{783470818, 2334330296, 116871553, 1683603268, 759950366, 3727285592, 3616407101, 525075992},
|
||||
{3899236298, 1976585972, 3822298095, 748204764, 2978121214, 200932224, 1340374715, 79506611},
|
||||
{4128139198, 1939423978, 3727937787, 1855257827, 630776586, 3470334826, 2498269262, 1495682436},
|
||||
{1348892970, 629870637, 3595702369, 770535689, 2256370736, 3444863052, 891128487, 33159341},
|
||||
{2967968932, 4261332726, 2399871138, 3313204386, 3991787238, 3531989490, 1624489585, 1792543190},
|
||||
{2179587180, 3737311899, 6357632, 3727566655, 3147613619, 2123011127, 3097377147, 992191510},
|
||||
{2182997143, 4101668140, 1996814613, 3581332946, 867002512, 1843201087, 4223363546, 1928077695},
|
||||
{3028933890, 3818130584, 3557387839, 2374442829, 911787393, 770676400, 337096879, 240174663},
|
||||
{3043672379, 1899171261, 504182702, 3054796849, 3828295843, 671705157, 3825173996, 1414902488},
|
||||
{376706115, 4194608423, 3594444823, 1625946449, 403768163, 2456846785, 44584848, 84202017},
|
||||
{3064390814, 2716996388, 3897127426, 2552999677, 3013912747, 1452854892, 3978189518, 1284784196},
|
||||
{3199468428, 2903114874, 72247584, 2410968068, 2003524493, 4123634338, 435261870, 701486964},
|
||||
{828746335, 3913770139, 1618218172, 3278121503, 2079247718, 1978636954, 910397289, 96552693},
|
||||
{2211749314, 3357848024, 3537465382, 3532697268, 2132182736, 1966921197, 1315441937, 1777448477},
|
||||
{2200248661, 391584476, 2234387592, 2850080717, 2653523993, 3210840164, 2903237762, 1794426612},
|
||||
{554961316, 3167917252, 4221707975, 1012517545, 736753739, 110159932, 145505695, 227111964},
|
||||
{3875411415, 1613987934, 1084962884, 3019340126, 2315514976, 2094187263, 3497819348, 291280352},
|
||||
{1739154213, 3075259556, 3948002791, 1367585114, 1701733509, 3623455345, 3493135301, 1923303618},
|
||||
{1827158133, 3185981038, 878567088, 2821327133, 3663194195, 4207640486, 3564098674, 1184657196},
|
||||
{3758205899, 815333136, 2869440132, 1818787811, 1081254131, 1686248084, 1041506138, 381361493},
|
||||
{3628751007, 777692999, 4180345157, 4240314964, 3494907162, 692170506, 2009935286, 1322780120},
|
||||
{887413708, 23343153, 3555916162, 3334619375, 2777783869, 2643155742, 1986000428, 630137915},
|
||||
{4096942349, 4145995447, 897723766, 2990805409, 4029167381, 2495258909, 4088391249, 609264602},
|
||||
{612790660, 2661534473, 247248263, 1136855857, 1161947150, 1315488261, 3680235769, 1229555413},
|
||||
{722881024, 192705355, 1754502243, 2697508301, 2945854931, 3504159885, 3445165630, 238076059},
|
||||
{222219657, 3437798818, 2744917536, 224256950, 1904282056, 105073736, 772693683, 292110801},
|
||||
{1796528306, 837471306, 1567726322, 1897641954, 3078024748, 3325524011, 3385455562, 951015556},
|
||||
{2407829502, 3164486936, 1487657, 4182947136, 3849960947, 3830817126, 1138850753, 130868390},
|
||||
{1678448871, 4289024418, 2650638643, 67119139, 3182458352, 3617797334, 628056031, 191722155},
|
||||
{3324568052, 2439834493, 375051932, 2170654759, 2348874396, 3713035811, 4199471222, 283037510},
|
||||
{773651958, 2125754199, 199104117, 213977251, 367104435, 3157051288, 2326732794, 275408701},
|
||||
{2460311739, 1791145889, 3915204508, 1272346229, 2834150762, 3900627326, 148310662, 1750293843},
|
||||
{2130280064, 2159064112, 1437026429, 2733029067, 294236910, 1031342011, 2050658606, 1599487766},
|
||||
{1105683188, 141496307, 1055256037, 646629220, 2520569043, 2475709708, 3396934601, 14464324},
|
||||
{2583712422, 1775337336, 2707695021, 1832388440, 4273340329, 2820244513, 2507193407, 1404928203},
|
||||
{1269867733, 2223696603, 1861500459, 2421626755, 3502911196, 2815315379, 549184699, 16975667},
|
||||
{426922700, 3601088398, 4218337357, 1790978582, 4136866168, 4035715442, 2326873078, 235501400},
|
||||
{3402079655, 566662668, 553974537, 3190505572, 1786065459, 1789792927, 1424842205, 1816440650},
|
||||
{3848752806, 4260216223, 570978505, 2129098465, 232557756, 7106551, 687416267, 1391264097},
|
||||
{670044537, 331678659, 344646513, 3012645076, 36483293, 2753421815, 1891477861, 132172653},
|
||||
{7972615, 3961288035, 486739371, 228490819, 1675833723, 2413801880, 3168288162, 1168358009},
|
||||
{1158898905, 554620687, 1047964985, 3481289834, 4201243048, 75670413, 821867979, 231202146},
|
||||
{520239323, 1484416551, 3247647509, 1403067553, 1541879850, 3785630405, 1117276684, 85930988},
|
||||
{1931565112, 3470042772, 3537431410, 2318191566, 3569616629, 726769301, 1627396145, 328822231},
|
||||
{1678673875, 3628799819, 1857961535, 915186097, 3107622699, 3356035428, 3569404983, 1026648178},
|
||||
{913100268, 3846074625, 3740179720, 3454441980, 4093733473, 1346792008, 1163703973, 57404821},
|
||||
{1519620766, 1446603960, 2393223713, 1459282094, 1023092791, 2199286418, 2096208360, 699051559},
|
||||
{2219754787, 2500265080, 191792189, 1542645732, 1161454113, 2969905865, 3687236724, 10987900},
|
||||
{1743254412, 82672506, 3135049363, 887561904, 928784698, 2657646376, 288207897, 435585205},
|
||||
{3465517945, 3661905420, 2283191968, 3144869509, 3579046583, 2037447473, 1533911765, 211714799},
|
||||
{2496160147, 1418604384, 1802507016, 1336309157, 1184402515, 206535898, 128178254, 1130299949},
|
||||
{1961044967, 3019089825, 2997612316, 265811573, 3263223461, 3365214238, 1135984798, 1595605265},
|
||||
{1483975027, 2808544081, 229106190, 450319819, 1309534945, 3830732771, 1124125013, 281790638},
|
||||
{3747100452, 107125028, 607240855, 1725178756, 3597437256, 3348335091, 2059188672, 1306485825},
|
||||
{79235387, 3022164429, 1311047830, 3155028639, 916354506, 2279445426, 83551349, 1018957398},
|
||||
{2095857719, 3787514231, 1479065116, 482814220, 2228714165, 221954960, 4265971691, 1649347513},
|
||||
{3188516880, 3597244272, 108997607, 353456206, 3223447432, 446895619, 2424498673, 1113641309},
|
||||
{57226169, 310268999, 3047208456, 3667872449, 1342874028, 1962131723, 2203612281, 717247378},
|
||||
{2523858162, 3604519783, 975513559, 4197094359, 2071686613, 2849799672, 321527978, 1319949504},
|
||||
{1913310732, 564832490, 732308813, 2586688178, 4054037287, 2720587232, 909207782, 1001626679},
|
||||
{4229590794, 3110228758, 4161959585, 4143451607, 1274301898, 499710233, 2801297171, 1696629637},
|
||||
{4283094591, 2041587860, 4272909686, 3032518657, 1275782421, 638738833, 562322176, 1764251529},
|
||||
{2166709661, 2507730084, 2167347676, 730353949, 4164042092, 702353215, 1692356174, 630374766},
|
||||
{4139857027, 2019739214, 1365461556, 190724658, 3746881101, 1551936264, 2542716346, 641014892},
|
||||
{3705816562, 1108147156, 1905372056, 2828808730, 1103318054, 1094456706, 1691237212, 559553895},
|
||||
{4190357473, 2752760058, 3475907929, 138551448, 2308123641, 1481331661, 4250021059, 794197070},
|
||||
{2204086692, 2614018999, 4066699829, 2915251952, 1331110005, 2166000553, 3772671276, 708029528},
|
||||
{3657760721, 2239870589, 436271478, 2779795192, 24689995, 1297075264, 1671988556, 523339184},
|
||||
{884023061, 652621983, 62069329, 1533423970, 279751135, 1384150035, 2787913666, 1184536494},
|
||||
{3832683369, 3220024363, 3898646445, 3616156349, 1816361908, 58265014, 2258645744, 1322185408},
|
||||
{2186663972, 992823504, 580939809, 4134674086, 3099356555, 1833300007, 689911450, 1656492952},
|
||||
{702913923, 1119558248, 3418804320, 2560686829, 3844756959, 2394009955, 1587731805, 1401231027},
|
||||
{3358386685, 971450419, 3942097807, 1751903613, 2010516544, 1867306049, 3690714201, 1210488397},
|
||||
{3401698520, 536404836, 794977212, 3865401272, 293002110, 51547193, 2792668565, 794288943},
|
||||
{2535122179, 3301198404, 1831226988, 939065116, 2928600716, 482930544, 1250716156, 1762491790},
|
||||
{754984898, 38001923, 2689392564, 1026928647, 489115662, 455738937, 2410612830, 1307198941},
|
||||
{172844518, 1699952276, 1485123703, 1156671318, 3179094813, 1188798431, 112551259, 1847940720},
|
||||
{3545208113, 2289833538, 2649086240, 2023989097, 3349947852, 696893462, 687717267, 1856396125},
|
||||
{3910459449, 3705304614, 3532442943, 3481251226, 895301896, 2986084489, 3299258047, 1761424967},
|
||||
{2725674291, 116532222, 3565763434, 1451215632, 1092995942, 2035526239, 1045737445, 1613646521},
|
||||
{4130593726, 3024687204, 1021306812, 2469430501, 497194315, 2974581792, 1255017536, 597255305},
|
||||
{523876618, 761620533, 3490119046, 1051900320, 1477617871, 2040477122, 3099679769, 1824205879},
|
||||
{4238414613, 3935907273, 2701284094, 1435298493, 2842895400, 3094051424, 2033163260, 1083623692},
|
||||
{642361789, 1604941380, 2400216156, 566375932, 30286136, 1212333003, 4008803597, 1648114656},
|
||||
{4152681515, 2343918434, 2094367525, 1848475261, 1968024081, 2889245354, 3005464900, 1786065752},
|
||||
{1081950398, 3116162259, 3148939719, 2734634826, 499009055, 1696427234, 1357324515, 801013715},
|
||||
{998077513, 4143316008, 3160753512, 1619454701, 647700665, 2041647364, 4250743448, 876294208},
|
||||
{42525978, 2569996457, 3426184151, 3354583607, 4034764830, 1228943658, 894711986, 618735436},
|
||||
{885919544, 1214434554, 3367715898, 2051767156, 3953912206, 4149513394, 37475677, 727749078},
|
||||
{4011510622, 1671330619, 385068934, 1150628512, 1425291267, 724496539, 1547726122, 746328500},
|
||||
};
|
||||
|
||||
for (int i = 0; i < digests_len; i++) {
|
||||
scalar_t root = digests[i];
|
||||
assert(root == expected[i]);
|
||||
}
|
||||
free(digests);
|
||||
free(leaves);
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -34,7 +34,7 @@ namespace utils_internal {
|
||||
{
|
||||
int tid = blockDim.x * blockIdx.x + threadIdx.x;
|
||||
if (tid < n_elements * batch_size) {
|
||||
int scalar_id = tid % n_elements;
|
||||
int64_t scalar_id = tid % n_elements;
|
||||
if (bitrev) scalar_id = __brev(scalar_id) >> (32 - logn);
|
||||
out_vec[tid] = *(scalar_vec + ((scalar_id * step) % n_scalars)) * in_vec[tid];
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "icicle-core"
|
||||
version = "1.0.0"
|
||||
version = "1.2.0"
|
||||
edition = "2021"
|
||||
authors = [ "Ingonyama" ]
|
||||
description = "A library for GPU ZK acceleration by Ingonyama"
|
||||
|
||||
@@ -3,10 +3,12 @@ pub mod error;
|
||||
pub mod field;
|
||||
pub mod msm;
|
||||
pub mod ntt;
|
||||
pub mod poseidon;
|
||||
#[cfg(feature = "arkworks")]
|
||||
#[doc(hidden)]
|
||||
pub mod tests;
|
||||
pub mod traits;
|
||||
pub mod tree;
|
||||
|
||||
pub trait SNARKCurve: curve::Curve + msm::MSM<Self>
|
||||
where
|
||||
|
||||
@@ -208,7 +208,7 @@ macro_rules! impl_ntt_tests {
|
||||
(
|
||||
$field:ident
|
||||
) => {
|
||||
const MAX_SIZE: u64 = 1 << 16;
|
||||
const MAX_SIZE: u64 = 1 << 17;
|
||||
static INIT: OnceLock<()> = OnceLock::new();
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -48,7 +48,7 @@ where
|
||||
F::ArkEquivalent: FftField,
|
||||
<F as FieldImpl>::Config: NTT<F> + GenerateRandom<F>,
|
||||
{
|
||||
let test_sizes = [1 << 4, 1 << 16];
|
||||
let test_sizes = [1 << 4, 1 << 17];
|
||||
for test_size in test_sizes {
|
||||
let ark_domain = GeneralEvaluationDomain::<F::ArkEquivalent>::new(test_size).unwrap();
|
||||
|
||||
@@ -161,7 +161,7 @@ where
|
||||
<F as FieldImpl>::Config: NTT<F> + GenerateRandom<F>,
|
||||
{
|
||||
let mut seed = test_rng();
|
||||
let test_sizes = [1 << 4, 1 << 16];
|
||||
let test_sizes = [1 << 4, 1 << 17];
|
||||
for test_size in test_sizes {
|
||||
let coset_generators = [
|
||||
F::ArkEquivalent::rand(&mut seed),
|
||||
|
||||
307
wrappers/rust/icicle-core/src/poseidon/mod.rs
Normal file
307
wrappers/rust/icicle-core/src/poseidon/mod.rs
Normal file
@@ -0,0 +1,307 @@
|
||||
#[doc(hidden)]
|
||||
pub mod tests;
|
||||
|
||||
use icicle_cuda_runtime::{
|
||||
device_context::{get_default_device_context, DeviceContext},
|
||||
memory::HostOrDeviceSlice,
|
||||
};
|
||||
|
||||
use crate::{error::IcicleResult, traits::FieldImpl};
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct PoseidonConstants<'a, F: FieldImpl> {
|
||||
arity: u32,
|
||||
|
||||
partial_rounds: u32,
|
||||
|
||||
full_rounds_half: u32,
|
||||
|
||||
/// These should be pointers to data allocated on device
|
||||
round_constants: &'a [F],
|
||||
mds_matrix: &'a [F],
|
||||
non_sparse_matrix: &'a [F],
|
||||
sparse_matrices: &'a [F],
|
||||
|
||||
/// Domain tag is the first element in the Poseidon state.
|
||||
/// For the Merkle tree mode it should equal 2^arity - 1
|
||||
domain_tag: F,
|
||||
}
|
||||
|
||||
/// Struct that encodes Poseidon parameters to be passed into the [poseidon_hash_many](poseidon_hash_many) function.
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct PoseidonConfig<'a> {
|
||||
/// Details related to the device such as its id and stream id. See [DeviceContext](@ref device_context::DeviceContext).
|
||||
pub ctx: DeviceContext<'a>,
|
||||
|
||||
are_inputs_on_device: bool,
|
||||
|
||||
are_outputs_on_device: bool,
|
||||
|
||||
/// If true, input is considered to be a states vector, holding the preimages
|
||||
/// in aligned or not aligned format. Memory under the input pointer will be used for states
|
||||
/// If false, fresh states memory will be allocated and input will be copied into it
|
||||
pub input_is_a_state: bool,
|
||||
|
||||
/// If true - input should be already aligned for poseidon permutation.
|
||||
/// Aligned format: [0, A, B, 0, C, D, ...] (as you might get by using loop_state)
|
||||
/// not aligned format: [A, B, 0, C, D, 0, ...] (as you might get from cudaMemcpy2D)
|
||||
pub aligned: bool,
|
||||
|
||||
/// If true, hash results will also be copied in the input pointer in aligned format
|
||||
pub loop_state: bool,
|
||||
|
||||
/// Whether to run Poseidon asynchronously. If set to `true`, Poseidon will be non-blocking
|
||||
/// and you'd need to synchronize it explicitly by running `cudaStreamSynchronize` or `cudaDeviceSynchronize`.
|
||||
/// If set to `false`, Poseidon will block the current CPU thread.
|
||||
pub is_async: bool,
|
||||
}
|
||||
|
||||
impl<'a> Default for PoseidonConfig<'a> {
|
||||
fn default() -> Self {
|
||||
let ctx = get_default_device_context();
|
||||
Self {
|
||||
ctx,
|
||||
are_inputs_on_device: false,
|
||||
are_outputs_on_device: false,
|
||||
input_is_a_state: false,
|
||||
aligned: false,
|
||||
loop_state: false,
|
||||
is_async: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait Poseidon<F: FieldImpl> {
|
||||
fn create_optimized_constants<'a>(
|
||||
arity: u32,
|
||||
full_rounds_half: u32,
|
||||
partial_rounds: u32,
|
||||
constants: &mut [F],
|
||||
ctx: &DeviceContext,
|
||||
) -> IcicleResult<PoseidonConstants<'a, F>>;
|
||||
fn load_optimized_constants<'a>(arity: u32, ctx: &DeviceContext) -> IcicleResult<PoseidonConstants<'a, F>>;
|
||||
fn poseidon_unchecked(
|
||||
input: &mut HostOrDeviceSlice<F>,
|
||||
output: &mut HostOrDeviceSlice<F>,
|
||||
number_of_states: u32,
|
||||
arity: u32,
|
||||
constants: &PoseidonConstants<F>,
|
||||
config: &PoseidonConfig,
|
||||
) -> IcicleResult<()>;
|
||||
}
|
||||
|
||||
/// Loads pre-calculated poseidon constants on the GPU.
|
||||
pub fn load_optimized_poseidon_constants<'a, F>(
|
||||
arity: u32,
|
||||
ctx: &DeviceContext,
|
||||
) -> IcicleResult<PoseidonConstants<'a, F>>
|
||||
where
|
||||
F: FieldImpl,
|
||||
<F as FieldImpl>::Config: Poseidon<F>,
|
||||
{
|
||||
<<F as FieldImpl>::Config as Poseidon<F>>::load_optimized_constants(arity, ctx)
|
||||
}
|
||||
|
||||
/// Creates new instance of poseidon constants on the GPU.
|
||||
pub fn create_optimized_poseidon_constants<'a, F>(
|
||||
arity: u32,
|
||||
ctx: &DeviceContext,
|
||||
full_rounds_half: u32,
|
||||
partial_rounds: u32,
|
||||
constants: &mut [F],
|
||||
) -> IcicleResult<PoseidonConstants<'a, F>>
|
||||
where
|
||||
F: FieldImpl,
|
||||
<F as FieldImpl>::Config: Poseidon<F>,
|
||||
{
|
||||
<<F as FieldImpl>::Config as Poseidon<F>>::create_optimized_constants(
|
||||
arity,
|
||||
full_rounds_half,
|
||||
partial_rounds,
|
||||
constants,
|
||||
ctx,
|
||||
)
|
||||
}
|
||||
|
||||
/// Computes the poseidon hashes for multiple preimages.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `input` - a pointer to the input data. May point to a vector of preimages or a vector of states filled with preimages.
|
||||
///
|
||||
/// * `output` - a pointer to the output data. Must be at least of size [number_of_states](number_of_states)
|
||||
///
|
||||
/// * `number_of_states` - number of input blocks of size `arity`
|
||||
///
|
||||
/// * `arity` - the arity of the hash function (the size of 1 preimage)
|
||||
///
|
||||
/// * `constants` - Poseidon constants.
|
||||
///
|
||||
/// * `config` - config used to specify extra arguments of the Poseidon.
|
||||
pub fn poseidon_hash_many<F>(
|
||||
input: &mut HostOrDeviceSlice<F>,
|
||||
output: &mut HostOrDeviceSlice<F>,
|
||||
number_of_states: u32,
|
||||
arity: u32,
|
||||
constants: &PoseidonConstants<F>,
|
||||
config: &PoseidonConfig,
|
||||
) -> IcicleResult<()>
|
||||
where
|
||||
F: FieldImpl,
|
||||
<F as FieldImpl>::Config: Poseidon<F>,
|
||||
{
|
||||
let input_len_required = if config.input_is_a_state {
|
||||
number_of_states * (arity + 1)
|
||||
} else {
|
||||
number_of_states * arity
|
||||
};
|
||||
|
||||
if input.len() < input_len_required as usize {
|
||||
panic!(
|
||||
"input len is {}; but needs to be at least {}",
|
||||
input.len(),
|
||||
input_len_required
|
||||
);
|
||||
}
|
||||
|
||||
if output.len() < number_of_states as usize {
|
||||
panic!(
|
||||
"output len is {}; but needs to be at least {}",
|
||||
output.len(),
|
||||
number_of_states
|
||||
);
|
||||
}
|
||||
|
||||
let mut local_cfg = config.clone();
|
||||
local_cfg.are_inputs_on_device = input.is_on_device();
|
||||
local_cfg.are_outputs_on_device = output.is_on_device();
|
||||
|
||||
<<F as FieldImpl>::Config as Poseidon<F>>::poseidon_unchecked(
|
||||
input,
|
||||
output,
|
||||
number_of_states,
|
||||
arity,
|
||||
constants,
|
||||
&local_cfg,
|
||||
)
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! impl_poseidon {
|
||||
(
|
||||
$field_prefix:literal,
|
||||
$field_prefix_ident:ident,
|
||||
$field:ident,
|
||||
$field_config:ident
|
||||
) => {
|
||||
mod $field_prefix_ident {
|
||||
use crate::poseidon::{$field, $field_config, CudaError, DeviceContext, PoseidonConfig, PoseidonConstants};
|
||||
extern "C" {
|
||||
#[link_name = concat!($field_prefix, "CreateOptimizedPoseidonConstants")]
|
||||
pub(crate) fn _create_optimized_constants(
|
||||
arity: u32,
|
||||
full_rounds_half: u32,
|
||||
partial_rounds: u32,
|
||||
constants: *mut $field,
|
||||
ctx: &DeviceContext,
|
||||
poseidon_constants: *mut PoseidonConstants<$field>,
|
||||
) -> CudaError;
|
||||
|
||||
#[link_name = concat!($field_prefix, "InitOptimizedPoseidonConstants")]
|
||||
pub(crate) fn _load_optimized_constants(
|
||||
arity: u32,
|
||||
ctx: &DeviceContext,
|
||||
constants: *mut PoseidonConstants<$field>,
|
||||
) -> CudaError;
|
||||
|
||||
#[link_name = concat!($field_prefix, "PoseidonHash")]
|
||||
pub(crate) fn hash_many(
|
||||
input: *mut $field,
|
||||
output: *mut $field,
|
||||
number_of_states: u32,
|
||||
arity: u32,
|
||||
constants: &PoseidonConstants<$field>,
|
||||
config: &PoseidonConfig,
|
||||
) -> CudaError;
|
||||
}
|
||||
}
|
||||
|
||||
impl Poseidon<$field> for $field_config {
|
||||
fn create_optimized_constants<'a>(
|
||||
arity: u32,
|
||||
full_rounds_half: u32,
|
||||
partial_rounds: u32,
|
||||
constants: &mut [$field],
|
||||
ctx: &DeviceContext,
|
||||
) -> IcicleResult<PoseidonConstants<'a, $field>> {
|
||||
unsafe {
|
||||
let mut poseidon_constants = MaybeUninit::<PoseidonConstants<'a, $field>>::uninit();
|
||||
let err = $field_prefix_ident::_create_optimized_constants(
|
||||
arity,
|
||||
full_rounds_half,
|
||||
partial_rounds,
|
||||
constants as *mut _ as *mut $field,
|
||||
ctx,
|
||||
poseidon_constants.as_mut_ptr(),
|
||||
)
|
||||
.wrap();
|
||||
err.and(Ok(poseidon_constants.assume_init()))
|
||||
}
|
||||
}
|
||||
|
||||
fn load_optimized_constants<'a>(
|
||||
arity: u32,
|
||||
ctx: &DeviceContext,
|
||||
) -> IcicleResult<PoseidonConstants<'a, $field>> {
|
||||
unsafe {
|
||||
let mut constants = MaybeUninit::<PoseidonConstants<'a, $field>>::uninit();
|
||||
let err = $field_prefix_ident::_load_optimized_constants(arity, ctx, constants.as_mut_ptr()).wrap();
|
||||
err.and(Ok(constants.assume_init()))
|
||||
}
|
||||
}
|
||||
|
||||
fn poseidon_unchecked(
|
||||
input: &mut HostOrDeviceSlice<$field>,
|
||||
output: &mut HostOrDeviceSlice<$field>,
|
||||
number_of_states: u32,
|
||||
arity: u32,
|
||||
constants: &PoseidonConstants<$field>,
|
||||
config: &PoseidonConfig,
|
||||
) -> IcicleResult<()> {
|
||||
unsafe {
|
||||
$field_prefix_ident::hash_many(
|
||||
input.as_mut_ptr(),
|
||||
output.as_mut_ptr(),
|
||||
number_of_states,
|
||||
arity,
|
||||
constants,
|
||||
config,
|
||||
)
|
||||
.wrap()
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! impl_poseidon_tests {
|
||||
(
|
||||
$field:ident,
|
||||
$field_bytes:literal,
|
||||
$field_prefix:literal,
|
||||
$partial_rounds:literal
|
||||
) => {
|
||||
#[test]
|
||||
fn test_poseidon_hash_many() {
|
||||
check_poseidon_hash_many::<$field>()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_poseidon_custom_config() {
|
||||
check_poseidon_custom_config::<$field>($field_bytes, $field_prefix, $partial_rounds)
|
||||
}
|
||||
};
|
||||
}
|
||||
104
wrappers/rust/icicle-core/src/poseidon/tests.rs
Normal file
104
wrappers/rust/icicle-core/src/poseidon/tests.rs
Normal file
@@ -0,0 +1,104 @@
|
||||
use crate::traits::FieldImpl;
|
||||
use icicle_cuda_runtime::device_context::get_default_device_context;
|
||||
use icicle_cuda_runtime::memory::HostOrDeviceSlice;
|
||||
|
||||
use std::io::Read;
|
||||
use std::path::PathBuf;
|
||||
use std::{env, fs::File};
|
||||
|
||||
use super::{
|
||||
create_optimized_poseidon_constants, load_optimized_poseidon_constants, poseidon_hash_many, Poseidon,
|
||||
PoseidonConfig, PoseidonConstants,
|
||||
};
|
||||
|
||||
pub fn init_poseidon<'a, F: FieldImpl>(arity: u32) -> PoseidonConstants<'a, F>
|
||||
where
|
||||
<F as FieldImpl>::Config: Poseidon<F>,
|
||||
{
|
||||
let ctx = get_default_device_context();
|
||||
|
||||
load_optimized_poseidon_constants::<F>(arity, &ctx).unwrap()
|
||||
}
|
||||
|
||||
pub fn _check_poseidon_hash_many<F: FieldImpl>(constants: PoseidonConstants<F>) -> (F, F)
|
||||
where
|
||||
<F as FieldImpl>::Config: Poseidon<F>,
|
||||
{
|
||||
let test_size = 1 << 10;
|
||||
let arity = 2u32;
|
||||
let inputs = vec![F::one(); test_size * arity as usize];
|
||||
let outputs = vec![F::zero(); test_size];
|
||||
|
||||
let mut input_slice = HostOrDeviceSlice::on_host(inputs);
|
||||
let mut output_slice = HostOrDeviceSlice::on_host(outputs);
|
||||
|
||||
let config = PoseidonConfig::default();
|
||||
poseidon_hash_many::<F>(
|
||||
&mut input_slice,
|
||||
&mut output_slice,
|
||||
test_size as u32,
|
||||
arity as u32,
|
||||
&constants,
|
||||
&config,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let a1 = output_slice[0..1][0];
|
||||
let a2 = output_slice[output_slice.len() - 2..output_slice.len() - 1][0];
|
||||
|
||||
println!("first: {:?}, last: {:?}", a1, a2);
|
||||
assert_eq!(a1, a2);
|
||||
|
||||
(a1, a2)
|
||||
}
|
||||
|
||||
pub fn check_poseidon_hash_many<F: FieldImpl>()
|
||||
where
|
||||
<F as FieldImpl>::Config: Poseidon<F>,
|
||||
{
|
||||
let arity = 2u32;
|
||||
let constants = init_poseidon::<F>(arity as u32);
|
||||
|
||||
_check_poseidon_hash_many(constants);
|
||||
}
|
||||
|
||||
pub fn check_poseidon_custom_config<F: FieldImpl>(field_bytes: usize, field_prefix: &str, partial_rounds: u32)
|
||||
where
|
||||
<F as FieldImpl>::Config: Poseidon<F>,
|
||||
{
|
||||
let arity = 2u32;
|
||||
let constants = init_poseidon::<F>(arity as u32);
|
||||
|
||||
let full_rounds_half = 4;
|
||||
|
||||
let ctx = get_default_device_context();
|
||||
let cargo_manifest_dir = env!("CARGO_MANIFEST_DIR");
|
||||
let constants_file = PathBuf::from(cargo_manifest_dir)
|
||||
.join("tests")
|
||||
.join(format!("{}_constants.bin", field_prefix));
|
||||
let mut constants_buf = vec![];
|
||||
File::open(constants_file)
|
||||
.unwrap()
|
||||
.read_to_end(&mut constants_buf)
|
||||
.unwrap();
|
||||
|
||||
let mut custom_constants = vec![];
|
||||
for chunk in constants_buf.chunks(field_bytes) {
|
||||
custom_constants.push(F::from_bytes_le(chunk));
|
||||
}
|
||||
|
||||
let custom_constants = create_optimized_poseidon_constants::<F>(
|
||||
arity as u32,
|
||||
&ctx,
|
||||
full_rounds_half,
|
||||
partial_rounds,
|
||||
&mut custom_constants,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let (a1, a2) = _check_poseidon_hash_many(constants);
|
||||
let (b1, b2) = _check_poseidon_hash_many(custom_constants);
|
||||
|
||||
assert_eq!(a1, b1);
|
||||
assert_eq!(a2, b2);
|
||||
}
|
||||
167
wrappers/rust/icicle-core/src/tree/mod.rs
Normal file
167
wrappers/rust/icicle-core/src/tree/mod.rs
Normal file
@@ -0,0 +1,167 @@
|
||||
use icicle_cuda_runtime::{
|
||||
device_context::{get_default_device_context, DeviceContext},
|
||||
memory::HostOrDeviceSlice,
|
||||
};
|
||||
|
||||
use crate::{error::IcicleResult, poseidon::PoseidonConstants, traits::FieldImpl};
|
||||
|
||||
#[doc(hidden)]
|
||||
pub mod tests;
|
||||
|
||||
/// Struct that encodes Tree Builder parameters to be passed into the [build_merkle_tree](build_merkle_tree) function.
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct TreeBuilderConfig<'a> {
|
||||
/// Details related to the device such as its id and stream id. See [DeviceContext](@ref device_context::DeviceContext).
|
||||
pub ctx: DeviceContext<'a>,
|
||||
|
||||
/// How many rows of the Merkle tree rows should be written to output. '0' means all of them
|
||||
keep_rows: u32,
|
||||
|
||||
are_inputs_on_device: bool,
|
||||
|
||||
/// Whether to run build_merkle_tree asynchronously. If set to `true`, TreeBuilder will be non-blocking
|
||||
/// and you'd need to synchronize it explicitly by running `cudaStreamSynchronize` or `cudaDeviceSynchronize`.
|
||||
/// If set to `false`, build_merkle_tree will block the current CPU thread.
|
||||
pub is_async: bool,
|
||||
}
|
||||
|
||||
impl<'a> Default for TreeBuilderConfig<'a> {
|
||||
fn default() -> Self {
|
||||
let ctx = get_default_device_context();
|
||||
Self {
|
||||
ctx,
|
||||
keep_rows: 0,
|
||||
are_inputs_on_device: false,
|
||||
is_async: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn merkle_tree_digests_len(height: u32, arity: u32) -> usize {
|
||||
let mut digests_len = 0usize;
|
||||
let mut row_length = 1;
|
||||
for _ in 1..height {
|
||||
digests_len += row_length;
|
||||
row_length *= arity as usize;
|
||||
}
|
||||
digests_len
|
||||
}
|
||||
|
||||
pub trait TreeBuilder<F: FieldImpl> {
|
||||
fn build_poseidon_tree_unchecked(
|
||||
leaves: &mut HostOrDeviceSlice<F>,
|
||||
digests: &mut [F],
|
||||
height: u32,
|
||||
arity: u32,
|
||||
constants: &PoseidonConstants<F>,
|
||||
config: &TreeBuilderConfig,
|
||||
) -> IcicleResult<()>;
|
||||
}
|
||||
|
||||
/// Builds a Poseidon Merkle tree.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `leaves` - a pointer to the leaves layer. Expected to have arity ^ (height - 1) elements
|
||||
///
|
||||
/// * `digests` - a pointer to the digests storage. Expected to have `sum(arity ^ (i)) for i in [0..height-1]`
|
||||
///
|
||||
/// * `height` - the height of the merkle tree
|
||||
///
|
||||
/// * `config` - config used to specify extra arguments of the Tree builder.
|
||||
pub fn build_poseidon_merkle_tree<F>(
|
||||
leaves: &mut HostOrDeviceSlice<F>,
|
||||
digests: &mut [F],
|
||||
height: u32,
|
||||
arity: u32,
|
||||
constants: &PoseidonConstants<F>,
|
||||
config: &TreeBuilderConfig,
|
||||
) -> IcicleResult<()>
|
||||
where
|
||||
F: FieldImpl,
|
||||
<F as FieldImpl>::Config: TreeBuilder<F>,
|
||||
{
|
||||
let leaves_len = 1 << (height - 1) as usize;
|
||||
if leaves.len() != leaves_len {
|
||||
panic!("Leaves len is {}; but needs to be exactly {}", leaves.len(), leaves_len,);
|
||||
}
|
||||
|
||||
let digests_len = merkle_tree_digests_len(height, arity);
|
||||
if digests.len() != digests_len as usize {
|
||||
panic!(
|
||||
"Digests len is {}; but needs to be exactly {}",
|
||||
digests.len(),
|
||||
digests_len
|
||||
);
|
||||
}
|
||||
|
||||
let mut local_cfg = config.clone();
|
||||
local_cfg.are_inputs_on_device = leaves.is_on_device();
|
||||
|
||||
<<F as FieldImpl>::Config as TreeBuilder<F>>::build_poseidon_tree_unchecked(
|
||||
leaves, digests, height, arity, constants, &local_cfg,
|
||||
)
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! impl_tree_builder {
|
||||
(
|
||||
$field_prefix:literal,
|
||||
$field_prefix_ident:ident,
|
||||
$field:ident,
|
||||
$field_config:ident
|
||||
) => {
|
||||
mod $field_prefix_ident {
|
||||
use crate::tree::{$field, $field_config, CudaError, DeviceContext, TreeBuilderConfig};
|
||||
use icicle_core::poseidon::PoseidonConstants;
|
||||
|
||||
extern "C" {
|
||||
#[link_name = concat!($field_prefix, "BuildPoseidonMerkleTree")]
|
||||
pub(crate) fn _build_poseidon_merkle_tree(
|
||||
leaves: *mut $field,
|
||||
digests: *mut $field,
|
||||
height: u32,
|
||||
arity: u32,
|
||||
constants: &PoseidonConstants<$field>,
|
||||
config: &TreeBuilderConfig,
|
||||
) -> CudaError;
|
||||
}
|
||||
}
|
||||
|
||||
impl TreeBuilder<$field> for $field_config {
|
||||
fn build_poseidon_tree_unchecked(
|
||||
leaves: &mut HostOrDeviceSlice<$field>,
|
||||
digests: &mut [$field],
|
||||
height: u32,
|
||||
arity: u32,
|
||||
constants: &PoseidonConstants<$field>,
|
||||
config: &TreeBuilderConfig,
|
||||
) -> IcicleResult<()> {
|
||||
unsafe {
|
||||
$field_prefix_ident::_build_poseidon_merkle_tree(
|
||||
leaves.as_mut_ptr(),
|
||||
digests as *mut _ as *mut $field,
|
||||
height,
|
||||
arity,
|
||||
constants,
|
||||
config,
|
||||
)
|
||||
.wrap()
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! impl_tree_builder_tests {
|
||||
(
|
||||
$field:ident
|
||||
) => {
|
||||
#[test]
|
||||
fn test_build_poseidon_merkle_tree() {
|
||||
check_build_merkle_tree::<$field>()
|
||||
}
|
||||
};
|
||||
}
|
||||
30
wrappers/rust/icicle-core/src/tree/tests.rs
Normal file
30
wrappers/rust/icicle-core/src/tree/tests.rs
Normal file
@@ -0,0 +1,30 @@
|
||||
use icicle_cuda_runtime::memory::HostOrDeviceSlice;
|
||||
|
||||
use crate::{
|
||||
poseidon::{tests::init_poseidon, Poseidon},
|
||||
traits::FieldImpl,
|
||||
tree::{build_poseidon_merkle_tree, merkle_tree_digests_len, TreeBuilderConfig},
|
||||
};
|
||||
|
||||
use super::TreeBuilder;
|
||||
|
||||
pub fn check_build_merkle_tree<F: FieldImpl>()
|
||||
where
|
||||
<F as FieldImpl>::Config: TreeBuilder<F> + Poseidon<F>,
|
||||
{
|
||||
let height = 20;
|
||||
let arity = 2;
|
||||
let keep_rows = 1;
|
||||
let leaves = vec![F::one(); 1 << (height - 1)];
|
||||
let mut digests = vec![F::zero(); merkle_tree_digests_len(height, arity)];
|
||||
|
||||
let mut leaves_slice = HostOrDeviceSlice::on_host(leaves);
|
||||
|
||||
let constants = init_poseidon(arity as u32);
|
||||
|
||||
let mut config = TreeBuilderConfig::default();
|
||||
config.keep_rows = keep_rows;
|
||||
build_poseidon_merkle_tree::<F>(&mut leaves_slice, &mut digests, height, arity, &constants, &config).unwrap();
|
||||
|
||||
println!("Root: {:?}", digests[0..1][0]);
|
||||
}
|
||||
BIN
wrappers/rust/icicle-core/tests/bls12_377_constants.bin
Normal file
BIN
wrappers/rust/icicle-core/tests/bls12_377_constants.bin
Normal file
Binary file not shown.
BIN
wrappers/rust/icicle-core/tests/bls12_381_constants.bin
Normal file
BIN
wrappers/rust/icicle-core/tests/bls12_381_constants.bin
Normal file
Binary file not shown.
BIN
wrappers/rust/icicle-core/tests/bn254_constants.bin
Normal file
BIN
wrappers/rust/icicle-core/tests/bn254_constants.bin
Normal file
Binary file not shown.
BIN
wrappers/rust/icicle-core/tests/bw6-761_constants.bin
Normal file
BIN
wrappers/rust/icicle-core/tests/bw6-761_constants.bin
Normal file
Binary file not shown.
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "icicle-cuda-runtime"
|
||||
version = "1.0.0"
|
||||
version = "1.2.0"
|
||||
edition = "2021"
|
||||
authors = [ "Ingonyama" ]
|
||||
description = "Ingonyama's Rust wrapper of CUDA runtime"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "icicle-bls12-377"
|
||||
version = "1.0.0"
|
||||
version = "1.2.0"
|
||||
edition = "2021"
|
||||
authors = [ "Ingonyama" ]
|
||||
description = "Rust wrapper for the CUDA implementation of BLS12-377 pairing friendly elliptic curve by Ingonyama"
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
pub mod curve;
|
||||
pub mod msm;
|
||||
pub mod ntt;
|
||||
pub mod poseidon;
|
||||
pub mod tree;
|
||||
|
||||
impl icicle_core::SNARKCurve for curve::CurveCfg {}
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
#[cfg(feature = "bw6-761")]
|
||||
use crate::curve::{BaseCfg, BaseField};
|
||||
use crate::curve::{ScalarCfg, ScalarField};
|
||||
|
||||
use icicle_core::error::IcicleResult;
|
||||
use icicle_core::impl_poseidon;
|
||||
use icicle_core::poseidon::{Poseidon, PoseidonConfig, PoseidonConstants};
|
||||
use icicle_core::traits::IcicleResultWrap;
|
||||
use icicle_cuda_runtime::device_context::DeviceContext;
|
||||
use icicle_cuda_runtime::error::CudaError;
|
||||
use icicle_cuda_runtime::memory::HostOrDeviceSlice;
|
||||
|
||||
use core::mem::MaybeUninit;
|
||||
|
||||
impl_poseidon!("bls12_377", bls12_377, ScalarField, ScalarCfg);
|
||||
|
||||
#[cfg(feature = "bw6-761")]
|
||||
impl_poseidon!("bw6_761", bw6_761, BaseField, BaseCfg);
|
||||
|
||||
#[cfg(test)]
|
||||
pub(crate) mod tests {
|
||||
use crate::curve::ScalarField;
|
||||
use icicle_core::impl_poseidon_tests;
|
||||
use icicle_core::poseidon::tests::*;
|
||||
|
||||
impl_poseidon_tests!(ScalarField, 32, "bls12_377", 56);
|
||||
}
|
||||
26
wrappers/rust/icicle-curves/icicle-bls12-377/src/tree/mod.rs
Normal file
26
wrappers/rust/icicle-curves/icicle-bls12-377/src/tree/mod.rs
Normal file
@@ -0,0 +1,26 @@
|
||||
#[cfg(feature = "bw6-761")]
|
||||
use crate::curve::{BaseCfg, BaseField};
|
||||
use crate::curve::{ScalarCfg, ScalarField};
|
||||
|
||||
use icicle_core::error::IcicleResult;
|
||||
use icicle_core::impl_tree_builder;
|
||||
use icicle_core::poseidon::PoseidonConstants;
|
||||
use icicle_core::traits::IcicleResultWrap;
|
||||
use icicle_core::tree::{TreeBuilder, TreeBuilderConfig};
|
||||
use icicle_cuda_runtime::device_context::DeviceContext;
|
||||
use icicle_cuda_runtime::error::CudaError;
|
||||
use icicle_cuda_runtime::memory::HostOrDeviceSlice;
|
||||
|
||||
impl_tree_builder!("bls12_377", bls12_377, ScalarField, ScalarCfg);
|
||||
|
||||
#[cfg(feature = "bw6-761")]
|
||||
impl_tree_builder!("bw6_761", bw6_761, BaseField, BaseCfg);
|
||||
|
||||
#[cfg(test)]
|
||||
pub(crate) mod tests {
|
||||
use crate::curve::ScalarField;
|
||||
use icicle_core::impl_tree_builder_tests;
|
||||
use icicle_core::tree::tests::*;
|
||||
|
||||
impl_tree_builder_tests!(ScalarField);
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "icicle-bls12-381"
|
||||
version = "1.0.0"
|
||||
version = "1.2.0"
|
||||
edition = "2021"
|
||||
authors = [ "Ingonyama" ]
|
||||
description = "Rust wrapper for the CUDA implementation of BLS12-381 pairing friendly elliptic curve by Ingonyama"
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
pub mod curve;
|
||||
pub mod msm;
|
||||
pub mod ntt;
|
||||
pub mod poseidon;
|
||||
pub mod tree;
|
||||
|
||||
impl icicle_core::SNARKCurve for curve::CurveCfg {}
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
use crate::curve::{ScalarCfg, ScalarField};
|
||||
|
||||
use icicle_core::error::IcicleResult;
|
||||
use icicle_core::impl_poseidon;
|
||||
use icicle_core::poseidon::{Poseidon, PoseidonConfig, PoseidonConstants};
|
||||
use icicle_core::traits::IcicleResultWrap;
|
||||
use icicle_cuda_runtime::device_context::DeviceContext;
|
||||
use icicle_cuda_runtime::error::CudaError;
|
||||
use icicle_cuda_runtime::memory::HostOrDeviceSlice;
|
||||
|
||||
use core::mem::MaybeUninit;
|
||||
|
||||
impl_poseidon!("bls12_381", bls12_381, ScalarField, ScalarCfg);
|
||||
|
||||
#[cfg(test)]
|
||||
pub(crate) mod tests {
|
||||
use crate::curve::ScalarField;
|
||||
use icicle_core::impl_poseidon_tests;
|
||||
use icicle_core::poseidon::tests::*;
|
||||
|
||||
impl_poseidon_tests!(ScalarField, 32, "bls12_381", 55);
|
||||
}
|
||||
21
wrappers/rust/icicle-curves/icicle-bls12-381/src/tree/mod.rs
Normal file
21
wrappers/rust/icicle-curves/icicle-bls12-381/src/tree/mod.rs
Normal file
@@ -0,0 +1,21 @@
|
||||
use crate::curve::{ScalarCfg, ScalarField};
|
||||
|
||||
use icicle_core::error::IcicleResult;
|
||||
use icicle_core::impl_tree_builder;
|
||||
use icicle_core::poseidon::PoseidonConstants;
|
||||
use icicle_core::traits::IcicleResultWrap;
|
||||
use icicle_core::tree::{TreeBuilder, TreeBuilderConfig};
|
||||
use icicle_cuda_runtime::device_context::DeviceContext;
|
||||
use icicle_cuda_runtime::error::CudaError;
|
||||
use icicle_cuda_runtime::memory::HostOrDeviceSlice;
|
||||
|
||||
impl_tree_builder!("bls12_381", bls12_381, ScalarField, ScalarCfg);
|
||||
|
||||
#[cfg(test)]
|
||||
pub(crate) mod tests {
|
||||
use crate::curve::ScalarField;
|
||||
use icicle_core::impl_tree_builder_tests;
|
||||
use icicle_core::tree::tests::*;
|
||||
|
||||
impl_tree_builder_tests!(ScalarField);
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "icicle-bn254"
|
||||
version = "1.0.0"
|
||||
version = "1.2.0"
|
||||
edition = "2021"
|
||||
authors = [ "Ingonyama" ]
|
||||
description = "Rust wrapper for the CUDA implementation of BN254 pairing friendly elliptic curve by Ingonyama"
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
pub mod curve;
|
||||
pub mod msm;
|
||||
pub mod ntt;
|
||||
pub mod poseidon;
|
||||
pub mod tree;
|
||||
|
||||
impl icicle_core::SNARKCurve for curve::CurveCfg {}
|
||||
|
||||
22
wrappers/rust/icicle-curves/icicle-bn254/src/poseidon/mod.rs
Normal file
22
wrappers/rust/icicle-curves/icicle-bn254/src/poseidon/mod.rs
Normal file
@@ -0,0 +1,22 @@
|
||||
use crate::curve::{ScalarCfg, ScalarField};
|
||||
|
||||
use icicle_core::error::IcicleResult;
|
||||
use icicle_core::impl_poseidon;
|
||||
use icicle_core::poseidon::{Poseidon, PoseidonConfig, PoseidonConstants};
|
||||
use icicle_core::traits::IcicleResultWrap;
|
||||
use icicle_cuda_runtime::device_context::DeviceContext;
|
||||
use icicle_cuda_runtime::error::CudaError;
|
||||
use icicle_cuda_runtime::memory::HostOrDeviceSlice;
|
||||
|
||||
use core::mem::MaybeUninit;
|
||||
|
||||
impl_poseidon!("bn254", bn254, ScalarField, ScalarCfg);
|
||||
|
||||
#[cfg(test)]
|
||||
pub(crate) mod tests {
|
||||
use crate::curve::ScalarField;
|
||||
use icicle_core::impl_poseidon_tests;
|
||||
use icicle_core::poseidon::tests::*;
|
||||
|
||||
impl_poseidon_tests!(ScalarField, 32, "bn254", 56);
|
||||
}
|
||||
21
wrappers/rust/icicle-curves/icicle-bn254/src/tree/mod.rs
Normal file
21
wrappers/rust/icicle-curves/icicle-bn254/src/tree/mod.rs
Normal file
@@ -0,0 +1,21 @@
|
||||
use crate::curve::{ScalarCfg, ScalarField};
|
||||
|
||||
use icicle_core::error::IcicleResult;
|
||||
use icicle_core::impl_tree_builder;
|
||||
use icicle_core::poseidon::PoseidonConstants;
|
||||
use icicle_core::traits::IcicleResultWrap;
|
||||
use icicle_core::tree::{TreeBuilder, TreeBuilderConfig};
|
||||
use icicle_cuda_runtime::device_context::DeviceContext;
|
||||
use icicle_cuda_runtime::error::CudaError;
|
||||
use icicle_cuda_runtime::memory::HostOrDeviceSlice;
|
||||
|
||||
impl_tree_builder!("bn254", bn254, ScalarField, ScalarCfg);
|
||||
|
||||
#[cfg(test)]
|
||||
pub(crate) mod tests {
|
||||
use crate::curve::ScalarField;
|
||||
use icicle_core::impl_tree_builder_tests;
|
||||
use icicle_core::tree::tests::*;
|
||||
|
||||
impl_tree_builder_tests!(ScalarField);
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "icicle-bw6-761"
|
||||
version = "1.0.0"
|
||||
version = "1.2.0"
|
||||
edition = "2021"
|
||||
authors = [ "Ingonyama" ]
|
||||
description = "Rust wrapper for the CUDA implementation of BW6-761 pairing friendly elliptic curve by Ingonyama"
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
pub mod curve;
|
||||
pub mod msm;
|
||||
pub mod ntt;
|
||||
pub mod poseidon;
|
||||
pub mod tree;
|
||||
|
||||
impl icicle_core::SNARKCurve for curve::CurveCfg {}
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
#[cfg(test)]
|
||||
pub(crate) mod tests {
|
||||
use crate::curve::ScalarField;
|
||||
use icicle_core::impl_poseidon_tests;
|
||||
use icicle_core::poseidon::tests::*;
|
||||
|
||||
impl_poseidon_tests!(ScalarField, 48, "bw6-761", 56);
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
#[cfg(test)]
|
||||
pub(crate) mod tests {
|
||||
use crate::curve::ScalarField;
|
||||
use icicle_core::impl_tree_builder_tests;
|
||||
use icicle_core::tree::tests::*;
|
||||
|
||||
impl_tree_builder_tests!(ScalarField);
|
||||
}
|
||||
Reference in New Issue
Block a user