diff --git a/Builds/CMake/RippledCore.cmake b/Builds/CMake/RippledCore.cmake index 74ff58f60..65c063bf8 100644 --- a/Builds/CMake/RippledCore.cmake +++ b/Builds/CMake/RippledCore.cmake @@ -488,6 +488,7 @@ target_sources (rippled PRIVATE src/ripple/app/tx/impl/apply.cpp src/ripple/app/tx/impl/applySteps.cpp src/ripple/app/hook/impl/applyHook.cpp + src/ripple/app/hook/impl/GasValidator.cpp src/ripple/app/tx/impl/details/NFTokenUtils.cpp #[===============================[ main sources: @@ -909,6 +910,7 @@ if (tests) src/test/jtx/impl/fee.cpp src/test/jtx/impl/flags.cpp src/test/jtx/impl/genesis.cpp + src/test/jtx/impl/hookgas.cpp src/test/jtx/impl/import.cpp src/test/jtx/impl/invoice_id.cpp src/test/jtx/impl/invoke.cpp diff --git a/hook/sfcodes.h b/hook/sfcodes.h index 8c7bc48f4..b0d546d2c 100644 --- a/hook/sfcodes.h +++ b/hook/sfcodes.h @@ -63,6 +63,8 @@ #define sfEmitGeneration ((2U << 16U) + 46U) #define sfLockCount ((2U << 16U) + 49U) #define sfFirstNFTokenSequence ((2U << 16U) + 50U) +#define sfHookInstructionCost ((2U << 16U) + 91U) +#define sfHookGas ((2U << 16U) + 92U) #define sfStartTime ((2U << 16U) + 93U) #define sfRepeatCount ((2U << 16U) + 94U) #define sfDelaySeconds ((2U << 16U) + 95U) diff --git a/src/ripple/app/hook/GasValidator.h b/src/ripple/app/hook/GasValidator.h new file mode 100644 index 000000000..91af41ee9 --- /dev/null +++ b/src/ripple/app/hook/GasValidator.h @@ -0,0 +1,57 @@ +//------------------------------------------------------------------------------ +/* + This file is part of rippled: https://github.com/ripple/rippled + Copyright (c) 2024 XRPL-Labs + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#ifndef RIPPLE_APP_HOOK_GASVALIDATOR_H_INCLUDED +#define RIPPLE_APP_HOOK_GASVALIDATOR_H_INCLUDED + +#include +#include +#include +#include +#include +#include +#include + +// Forward declaration +using GuardLog = + std::optional>>; + +namespace hook { + +/** + * @brief Validate WASM host functions for Gas-type hooks + * + * Validates that a WASM binary only imports allowed host functions + * and does not import the _g (guard) function, which is only for + * Guard-type hooks. + * + * @param wasm The WASM binary to validate + * @param guardLog Logging function for validation errors + * @param guardLogAccStr Account string for logging + * @return std::nullopt if validation succeeds, error message otherwise + */ +std::optional +validateWasmHostFunctionsForGas( + std::vector const& wasm, + ripple::Rules const& rules, + beast::Journal const& j); + +} // namespace hook + +#endif // RIPPLE_APP_HOOK_GASVALIDATOR_H_INCLUDED diff --git a/src/ripple/app/hook/applyHook.h b/src/ripple/app/hook/applyHook.h index 2c1f250bb..7eb19b173 100644 --- a/src/ripple/app/hook/applyHook.h +++ b/src/ripple/app/hook/applyHook.h @@ -10,7 +10,6 @@ #include #include #include -#include #include #include #include @@ -462,7 +461,9 @@ apply( uint32_t wasmParam, uint8_t hookChainPosition, // result of apply() if this is weak exec - std::shared_ptr const& provisionalMeta); + std::shared_ptr const& provisionalMeta, + uint16_t hookApiVersion, + uint32_t hookGas); struct HookContext; @@ -501,6 +502,7 @@ struct HookResult std::string exitReason{""}; int64_t exitCode{-1}; uint64_t instructionCount{0}; + uint64_t instructionCost{0}; bool hasCallback = false; // true iff this hook wasm has a cbak function bool isCallback = false; // true iff this hook execution is a callback in action @@ -513,6 +515,8 @@ struct HookResult false; // hook_again allows strong pre-apply to nominate // additional weak post-apply execution std::shared_ptr provisionalMeta; + uint16_t hookApiVersion = 0; // 0 = Guard-type, 1 = Gas-type + std::optional hookGas; // Gas limit for Gas-type hooks }; class HookExecutor; @@ -658,6 +662,7 @@ public: if (!conf) return; WasmEdge_ConfigureStatisticsSetInstructionCounting(conf, true); + WasmEdge_ConfigureStatisticsSetCostMeasuring(conf, true); ctx = WasmEdge_VMCreate(conf, NULL); } @@ -758,6 +763,23 @@ public: return; } + // Set Gas limit for Gas-type hooks (HookApiVersion == 1) + if (hookCtx.result.hookApiVersion == 1 && + hookCtx.result.hookGas.has_value()) + { + auto* statsCtx = WasmEdge_VMGetStatisticsContext(vm.ctx); + if (statsCtx) + { + // Convert HookGas to cost limit count (1 Gas = 1 cost) + uint32_t gasLimit = *hookCtx.result.hookGas; + WasmEdge_StatisticsSetCostLimit(statsCtx, gasLimit); + + JLOG(j.trace()) + << "HookInfo[" << HC_ACC() << "]: Set Gas limit to " + << gasLimit << " cost limit for Gas-type Hook"; + } + } + WasmEdge_Value params[1] = {WasmEdge_ValueGenI32((int64_t)wasmParam)}; WasmEdge_Value returns[1]; @@ -771,16 +793,28 @@ public: returns, 1); - if (auto err = getWasmError("WASM VM error", res); err) - { - JLOG(j.warn()) << "HookError[" << HC_ACC() << "]: " << *err; - hookCtx.result.exitType = hook_api::ExitType::WASM_ERROR; - return; - } - auto* statsCtx = WasmEdge_VMGetStatisticsContext(vm.ctx); hookCtx.result.instructionCount = WasmEdge_StatisticsGetInstrCount(statsCtx); + hookCtx.result.instructionCost = + WasmEdge_StatisticsGetTotalCost(statsCtx); + + if (auto err = getWasmError("WASM VM error", res); err) + { + JLOG(j.trace()) << "HookError[" << HC_ACC() << "]: " << *err; + + // Check if error is due to Gas limit exceeded for Gas-type hooks + if (hookCtx.result.hookApiVersion == 1 && + err->find("cost limit exceeded") != std::string::npos) + { + JLOG(j.trace()) << "HookError[" << HC_ACC() + << "]: Gas limit exceeded. Limit was " + << *hookCtx.result.hookGas << " instructions"; + } + + hookCtx.result.exitType = hook_api::ExitType::WASM_ERROR; + return; + } // RH NOTE: stack unwind will clean up WasmEdgeVM } diff --git a/src/ripple/app/hook/impl/GasValidator.cpp b/src/ripple/app/hook/impl/GasValidator.cpp new file mode 100644 index 000000000..fb06e71ca --- /dev/null +++ b/src/ripple/app/hook/impl/GasValidator.cpp @@ -0,0 +1,156 @@ +//------------------------------------------------------------------------------ +/* + This file is part of rippled: https://github.com/ripple/rippled + Copyright (c) 2024 XRPL-Labs + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#include +#include +#include +#include +#include +#include + +namespace hook { + +std::optional +validateWasmHostFunctionsForGas( + std::vector const& wasm, + Rules const& rules, + beast::Journal const& j) +{ + // Create WasmEdge Loader + WasmEdge_LoaderContext* loader = WasmEdge_LoaderCreate(NULL); + if (!loader) + { + return "Failed to create WasmEdge Loader"; + } + + // Parse WASM binary + WasmEdge_ASTModuleContext* astModule = NULL; + WasmEdge_Result res = WasmEdge_LoaderParseFromBuffer( + loader, &astModule, wasm.data(), wasm.size()); + + if (!WasmEdge_ResultOK(res)) + { + WasmEdge_LoaderDelete(loader); + const char* msg = WasmEdge_ResultGetMessage(res); + return std::string("Failed to parse WASM: ") + + (msg ? msg : "unknown error"); + } + + // Get import count + uint32_t importCount = WasmEdge_ASTModuleListImportsLength(astModule); + + if (importCount == 0) + { + WasmEdge_ASTModuleDelete(astModule); + WasmEdge_LoaderDelete(loader); + JLOG(j.trace()) << "HookSet(" << hook::log::IMPORTS_MISSING + << "): WASM must import at least hook API functions"; + return "WASM must import at least hook API functions"; + } + + // Get imports (max 256) + const WasmEdge_ImportTypeContext* imports[256]; + uint32_t actualImportCount = std::min(importCount, 256u); + actualImportCount = + WasmEdge_ASTModuleListImports(astModule, imports, actualImportCount); + + std::optional error; + + // Check each import + for (uint32_t i = 0; i < actualImportCount; i++) + { + WasmEdge_String moduleName = + WasmEdge_ImportTypeGetModuleName(imports[i]); + WasmEdge_String externalName = + WasmEdge_ImportTypeGetExternalName(imports[i]); + WasmEdge_ExternalType extType = + WasmEdge_ImportTypeGetExternalType(imports[i]); + + // Only check function imports + if (extType != WasmEdge_ExternalType_Function) + continue; + + // Convert WasmEdge_String to std::string for comparison + std::string modName(moduleName.Buf, moduleName.Length); + std::string extName(externalName.Buf, externalName.Length); + + // Check module name is "env" + if (modName != "env") + { + JLOG(j.trace()) + << "HookSet(" << hook::log::IMPORT_MODULE_ENV + << "): Import module must be 'env', found: " << modName; + error = "Import module must be 'env', found: " + modName; + break; + } + + // Check for forbidden _g function (guard function) + if (extName == "_g") + { + JLOG(j.trace()) + << "HookSet(" << hook::log::IMPORT_ILLEGAL + << "): Gas-type hooks cannot import _g (guard) function"; + error = "Gas-type hooks cannot import _g (guard) function"; + break; + } + + // Check external name length + if (extName.length() < 1 || extName.length() > 64) + { + JLOG(j.trace()) << "HookSet(" << hook::log::IMPORT_NAME_BAD + << "): Import name length invalid: " << extName; + error = "Import name length invalid: " + extName; + break; + } + + // Check against whitelist using find() + bool found = false; + + // Check base whitelist (import_whitelist) + if (hook_api::import_whitelist.find(extName) != + hook_api::import_whitelist.end()) + { + found = true; + } + + // Check extended whitelist (import_whitelist_1) + if (!found && rules.enabled(featureHooksUpdate1) && + hook_api::import_whitelist_1.find(extName) != + hook_api::import_whitelist_1.end()) + { + found = true; + } + + if (!found) + { + JLOG(j.trace()) << "HookSet(" << hook::log::IMPORT_ILLEGAL + << "): Import not in whitelist: " << extName; + error = "Import not in whitelist: " + extName; + break; + } + } + + // Cleanup + WasmEdge_ASTModuleDelete(astModule); + WasmEdge_LoaderDelete(loader); + + return error; +} + +} // namespace hook diff --git a/src/ripple/app/hook/impl/applyHook.cpp b/src/ripple/app/hook/impl/applyHook.cpp index f27b7d23b..7db12ae06 100644 --- a/src/ripple/app/hook/impl/applyHook.cpp +++ b/src/ripple/app/hook/impl/applyHook.cpp @@ -1232,7 +1232,9 @@ hook::apply( bool isStrong, uint32_t wasmParam, uint8_t hookChainPosition, - std::shared_ptr const& provisionalMeta) + std::shared_ptr const& provisionalMeta, + uint16_t hookApiVersion, + uint32_t hookGas) { HookContext hookCtx = { .applyCtx = applyCtx, @@ -1264,7 +1266,9 @@ hook::apply( .wasmParam = wasmParam, .hookChainPosition = hookChainPosition, .foreignStateSetDisabled = false, - .provisionalMeta = provisionalMeta}, + .provisionalMeta = provisionalMeta, + .hookApiVersion = hookApiVersion, + .hookGas = hookGas}, .emitFailure = isCallback && wasmParam & 1 ? std::optional( (*(applyCtx.view().peek(keylet::emittedTxn( @@ -2049,6 +2053,9 @@ hook::finalizeHookResult( ripple::Slice{ hookResult.exitReason.data(), hookResult.exitReason.size()}); meta.setFieldU64(sfHookInstructionCount, hookResult.instructionCount); + if (hookResult.hookApiVersion == 1) + meta.setFieldU32(sfHookInstructionCost, hookResult.instructionCost); + meta.setFieldU16( sfHookEmitCount, emission_txnid.size()); // this will never wrap, hard limit diff --git a/src/ripple/app/tx/impl/SetHook.cpp b/src/ripple/app/tx/impl/SetHook.cpp index 9ca829557..087eed6ec 100644 --- a/src/ripple/app/tx/impl/SetHook.cpp +++ b/src/ripple/app/tx/impl/SetHook.cpp @@ -20,6 +20,7 @@ #include #include +#include #include #include #include @@ -435,7 +436,8 @@ SetHook::validateHookSetEntry(SetHookCtx& ctx, STObject const& hookSetObj) } auto version = hookSetObj.getFieldU16(sfHookApiVersion); - if (version != 0) + + if (!ctx.rules.enabled(featureHookGas) && version != 0) { // we currently only accept api version 0 JLOG(ctx.j.trace()) @@ -445,6 +447,17 @@ SetHook::validateHookSetEntry(SetHookCtx& ctx, STObject const& hookSetObj) return false; } + // allow only version=0 and version=1 + if (version != 0 && version != 1) + { + JLOG(ctx.j.trace()) + << "HookSet(" << ::hook::log::API_INVALID << ")[" + << HS_ACC() + << "]: Malformed transaction: SetHook " + "sfHook->sfHookApiVersion invalid. (Must be 0 or 1)."; + return false; + } + // validate sfHookOn if (!hookSetObj.isFieldPresent(sfHookOn)) { @@ -469,6 +482,7 @@ SetHook::validateHookSetEntry(SetHookCtx& ctx, STObject const& hookSetObj) return {}; Blob hook = hookSetObj.getFieldVL(sfCreateCode); + auto version = hookSetObj.getFieldU16(sfHookApiVersion); // RH NOTE: validateGuards has a generic non-rippled specific // interface so it can be used in other projects (i.e. tooling). @@ -486,46 +500,83 @@ SetHook::validateHookSetEntry(SetHookCtx& ctx, STObject const& hookSetObj) hsacc = ss.str(); } - auto result = validateGuards( - hook, // wasm to verify - logger, - hsacc, - (ctx.rules.enabled(featureHooksUpdate1) ? 1 : 0) + - (ctx.rules.enabled(fix20250131) ? 2 : 0)); + uint64_t maxInstrCountHook = 0; + uint64_t maxInstrCountCbak = 0; - if (ctx.j.trace()) + if (version == 0) // Guard type { - // clunky but to get the stream to accept the output - // correctly we will split on new line and feed each line - // one by one into the trace stream beast::Journal should be - // updated to inherit from basic_ostream then this - // wouldn't be necessary. + auto result = validateGuards( + hook, // wasm to verify + logger, + hsacc, + (ctx.rules.enabled(featureHooksUpdate1) ? 1 : 0) + + (ctx.rules.enabled(fix20250131) ? 2 : 0)); - // is this a needless copy or does the compiler do copy - // elision here? - std::string s = loggerStream.str(); - - char* data = s.data(); - size_t len = s.size(); - - char* last = data; - size_t i = 0; - for (; i < len; ++i) + if (ctx.j.trace()) { - if (data[i] == '\n') + // clunky but to get the stream to accept the output + // correctly we will split on new line and feed each + // line one by one into the trace stream beast::Journal + // should be updated to inherit from basic_ostream + // then this wouldn't be necessary. + + // is this a needless copy or does the compiler do copy + // elision here? + std::string s = loggerStream.str(); + + char* data = s.data(); + size_t len = s.size(); + + char* last = data; + size_t i = 0; + for (; i < len; ++i) { - data[i] = '\0'; - ctx.j.trace() << last; - last = data + i; + if (data[i] == '\n') + { + data[i] = '\0'; + ctx.j.trace() << last; + last = data + i; + } } + + if (last < data + i) + ctx.j.trace() << last; } - if (last < data + i) - ctx.j.trace() << last; - } + if (!result) + { + JLOG(ctx.j.trace()) + << "HookSet(" << hook::log::WASM_BAD_MAGIC << ")[" + << HS_ACC() + << "]: Malformed transaction: SetHook " + "sfCreateCode failed validation."; + return false; + } - if (!result) - return false; + std::tie(maxInstrCountHook, maxInstrCountCbak) = *result; + } + else if (version == 1) // Gas type + { + // validate with GasValidator + auto error = hook::validateWasmHostFunctionsForGas( + hook, ctx.rules, ctx.j); + + if (error) + { + JLOG(ctx.j.trace()) + << "HookSet(" << hook::log::IMPORT_ILLEGAL << ")[" + << HS_ACC() + << "]: Malformed transaction: Gas-type Hook " + "validation failed: " + << *error; + return false; + } + + // Gas type: maxInstrCount is not pre-calculated (use Gas + // limit at runtime) + maxInstrCountHook = 0; + maxInstrCountCbak = 0; + } JLOG(ctx.j.trace()) << "HookSet(" << hook::log::WASM_SMOKE_TEST << ")[" @@ -547,7 +598,7 @@ SetHook::validateHookSetEntry(SetHookCtx& ctx, STObject const& hookSetObj) return false; } - return *result; + return std::make_pair(maxInstrCountHook, maxInstrCountCbak); } } @@ -1680,10 +1731,11 @@ SetHook::setHook() newHookDef->setFieldH256( sfHookSetTxnID, ctx.tx.getTransactionID()); newHookDef->setFieldU64(sfReferenceCount, 1); - newHookDef->setFieldAmount( - sfFee, - XRPAmount{ - hook::computeExecutionFee(maxInstrCountHook)}); + if (hookSetObj->get().getFieldU16(sfHookApiVersion) != 1) + newHookDef->setFieldAmount( + sfFee, + XRPAmount{ + hook::computeExecutionFee(maxInstrCountHook)}); if (maxInstrCountCbak > 0) newHookDef->setFieldAmount( sfHookCallbackFee, diff --git a/src/ripple/app/tx/impl/Transactor.cpp b/src/ripple/app/tx/impl/Transactor.cpp index 80646172a..dbb7cce22 100644 --- a/src/ripple/app/tx/impl/Transactor.cpp +++ b/src/ripple/app/tx/impl/Transactor.cpp @@ -100,6 +100,11 @@ preflight1(PreflightContext const& ctx) return temMALFORMED; } + if (ctx.tx.isFieldPresent(sfHookGas) && !ctx.rules.enabled(featureHookGas)) + { + return temMALFORMED; + } + auto const ret = preflight0(ctx); if (!isTesSuccess(ret)) return ret; @@ -219,6 +224,7 @@ Transactor::calculateHookChainFee( return XRPAmount{0}; XRPAmount fee{0}; + uint32_t gasTypeHookCount = 0; // Gas type hook counter auto const& hooks = hookSLE->getFieldArray(sfHooks); @@ -255,18 +261,43 @@ Transactor::calculateHookChainFee( if (hook::canHook(tx.getTxnType(), hookOn) && (!collectCallsOnly || (flags & hook::hsfCOLLECT))) { - XRPAmount const toAdd{hookDef->getFieldAmount(sfFee).xrp().drops()}; + // get HookApiVersion + uint16_t apiVersion = hookDef->getFieldU16(sfHookApiVersion); - // this overflow should never happen, if somehow it does - // fee is set to the largest possible valid xrp value to force - // fail the transaction - if (fee + toAdd < fee) - fee = XRPAmount{INITIAL_XRP.drops()}; - else - fee += toAdd; + if (apiVersion == 0) // Guard type + { + // existing logic: read HookDefinition's sfFee + XRPAmount const toAdd{ + hookDef->getFieldAmount(sfFee).xrp().drops()}; + + // this overflow should never happen, if somehow it does + // fee is set to the largest possible valid xrp value to force + // fail the transaction + if (fee + toAdd < fee) + fee = XRPAmount{INITIAL_XRP.drops()}; + else + fee += toAdd; + } + else if (apiVersion == 1) // Gas type + { + // Gas type: only count + gasTypeHookCount++; + } } } + // Additional cost for Gas type: 0.2 XAH/Hook = 200,000 drops/Hook + if (gasTypeHookCount > 0) + { + // TODO: + auto const baseGasFee = 200000; + XRPAmount const gasTypeFee{gasTypeHookCount * baseGasFee}; + if (fee + gasTypeFee < fee) + fee = XRPAmount{INITIAL_XRP.drops()}; // overflow + else + fee += gasTypeFee; + } + return fee; } @@ -346,6 +377,10 @@ Transactor::calculateBaseFee(ReadView const& view, STTx const& tx) if (canRollback) hookExecutionFee += calculateHookChainFee(view, tx, keylet::hook(tshAcc)); + + if (view.rules().enabled(featureHookGas) && + tx.isFieldPresent(sfHookGas)) + hookExecutionFee += XRPAmount{tx.getFieldU32(sfHookGas)}; } XRPAmount accumulator = baseFee; @@ -1194,6 +1229,15 @@ Transactor::executeHookChain( std::map, std::vector>> hookParamOverrides{}; + // Initialize Gas pool for Gas-type hooks + uint32_t gasPool = 0; + if (ctx_.tx.isFieldPresent(sfHookGas)) + { + gasPool = ctx_.tx.getFieldU32(sfHookGas); + JLOG(j_.trace()) << "HookChain: Initialized Gas pool with " << gasPool + << " instructions"; + } + auto const& hooks = hookSLE->getFieldArray(sfHooks); uint8_t hook_no = 0; @@ -1262,6 +1306,19 @@ Transactor::executeHookChain( bool hasCallback = hookDef->isFieldPresent(sfHookCallbackFee); + // Extract HookApiVersion for Gas-type hooks + uint16_t hookApiVersion = hookDef->isFieldPresent(sfHookApiVersion) + ? hookDef->getFieldU16(sfHookApiVersion) + : 0; + + // Prepare Gas limit for this hook execution + uint32_t hookGas = 0; + if (hookApiVersion == 1) + { + // Pass remaining Gas pool to this hook + hookGas = gasPool; + } + try { results.push_back(hook::apply( @@ -1280,12 +1337,35 @@ Transactor::executeHookChain( strong, (strong ? 0 : 1UL), // 0 = strong, 1 = weak hook_no - 1, - provisionalMeta)); + provisionalMeta, + hookApiVersion, + hookGas)); executedHookCount_++; hook::HookResult& hookResult = results.back(); + // Track Gas consumption for Gas-type hooks + if (hookApiVersion == 1) + { + uint64_t consumed = hookResult.instructionCost; + + JLOG(j_.trace()) << "HookChain: Hook consumed " << consumed + << " instructions. Pool before: " << gasPool; + + if (consumed >= gasPool) + { + JLOG(j_.trace()) << "HookError: Gas pool exhausted. " + << "Hook tried to consume " << consumed + << " but only " << gasPool << " remained."; + return tecHOOK_INSUFFICIENT_GAS; + } + + gasPool -= consumed; + + JLOG(j_.trace()) << "HookChain: Pool after: " << gasPool; + } + if (hookResult.exitType != hook_api::ExitType::ACCEPT) { if (results.back().exitType == hook_api::ExitType::WASM_ERROR) @@ -1422,6 +1502,17 @@ Transactor::doHookCallback( { hook::HookStateMap stateMap; + // Extract HookApiVersion for callback + uint16_t hookApiVersion = hookDef->getFieldU16(sfHookApiVersion); + + // Callbacks don't consume HookGas independently, but we pass it + // for consistency + uint32_t hookGas = 0; + if (ctx_.tx.isFieldPresent(sfHookGas)) + { + hookGas = ctx_.tx.getFieldU32(sfHookGas); + } + hook::HookResult callbackResult = hook::apply( hookDef->getFieldH256(sfHookSetTxnID), callbackHookHash, @@ -1441,7 +1532,9 @@ Transactor::doHookCallback( ? 1UL : 0UL, hook_no - 1, - provisionalMeta); + provisionalMeta, + hookApiVersion, + hookGas); executedHookCount_++; @@ -1717,6 +1810,14 @@ Transactor::doAgainAsWeak( return; } + // Extract HookApiVersion for aaw execution + uint16_t hookApiVersion = hookDef->getFieldU16(sfHookApiVersion); + + // Extract HookGas for Gas-type hooks + uint32_t hookGas = 0; + if (hookApiVersion == 1 && ctx_.tx.isFieldPresent(sfHookGas)) + hookGas = ctx_.tx.getFieldU32(sfHookGas); + try { hook::HookResult aawResult = hook::apply( @@ -1735,7 +1836,9 @@ Transactor::doAgainAsWeak( false, 2UL, // param 2 = aaw hook_no - 1, - provisionalMeta); + provisionalMeta, + hookApiVersion, + hookGas); executedHookCount_++; diff --git a/src/ripple/protocol/Feature.h b/src/ripple/protocol/Feature.h index 2766859dc..dd4b12903 100644 --- a/src/ripple/protocol/Feature.h +++ b/src/ripple/protocol/Feature.h @@ -74,7 +74,7 @@ namespace detail { // Feature.cpp. Because it's only used to reserve storage, and determine how // large to make the FeatureBitset, it MAY be larger. It MUST NOT be less than // the actual number of amendments. A LogicError on startup will verify this. -static constexpr std::size_t numFeatures = 90; +static constexpr std::size_t numFeatures = 91; /** Amendments that this server supports and the default voting behavior. Whether they are enabled depends on the Rules defined in the validated @@ -378,6 +378,7 @@ extern uint256 const fixInvalidTxFlags; extern uint256 const featureExtendedHookState; extern uint256 const fixCronStacking; extern uint256 const fixHookAPI20251128; +extern uint256 const featureHookGas; } // namespace ripple #endif diff --git a/src/ripple/protocol/SField.h b/src/ripple/protocol/SField.h index f507b2232..3bbf0a7e8 100644 --- a/src/ripple/protocol/SField.h +++ b/src/ripple/protocol/SField.h @@ -414,6 +414,8 @@ extern SF_UINT32 const sfXahauActivationLgrSeq; extern SF_UINT32 const sfDelaySeconds; extern SF_UINT32 const sfRepeatCount; extern SF_UINT32 const sfStartTime; +extern SF_UINT32 const sfHookGas; +extern SF_UINT32 const sfHookInstructionCost; // 64-bit integers (common) extern SF_UINT64 const sfIndexNext; diff --git a/src/ripple/protocol/TER.h b/src/ripple/protocol/TER.h index 573e0b628..7e18867ec 100644 --- a/src/ripple/protocol/TER.h +++ b/src/ripple/protocol/TER.h @@ -344,6 +344,7 @@ enum TECcodes : TERUnderlyingType { tecIMMUTABLE = 188, tecTOO_MANY_REMARKS = 189, tecHAS_HOOK_STATE = 190, + tecHOOK_INSUFFICIENT_GAS = 191, tecLAST_POSSIBLE_ENTRY = 255, }; diff --git a/src/ripple/protocol/impl/Feature.cpp b/src/ripple/protocol/impl/Feature.cpp index 24383f896..5293e52d8 100644 --- a/src/ripple/protocol/impl/Feature.cpp +++ b/src/ripple/protocol/impl/Feature.cpp @@ -484,6 +484,7 @@ REGISTER_FIX (fixInvalidTxFlags, Supported::yes, VoteBehavior::De REGISTER_FEATURE(ExtendedHookState, Supported::yes, VoteBehavior::DefaultNo); REGISTER_FIX (fixCronStacking, Supported::yes, VoteBehavior::DefaultYes); REGISTER_FIX (fixHookAPI20251128, Supported::yes, VoteBehavior::DefaultYes); +REGISTER_FEATURE(HookGas, Supported::yes, VoteBehavior::DefaultYes); // The following amendments are obsolete, but must remain supported // because they could potentially get enabled. diff --git a/src/ripple/protocol/impl/InnerObjectFormats.cpp b/src/ripple/protocol/impl/InnerObjectFormats.cpp index 4c2500ff2..8e8bd8481 100644 --- a/src/ripple/protocol/impl/InnerObjectFormats.cpp +++ b/src/ripple/protocol/impl/InnerObjectFormats.cpp @@ -73,7 +73,8 @@ InnerObjectFormats::InnerObjectFormats() {sfHookExecutionIndex, soeREQUIRED}, {sfHookStateChangeCount, soeREQUIRED}, {sfHookEmitCount, soeREQUIRED}, - {sfFlags, soeOPTIONAL}}); + {sfFlags, soeOPTIONAL}, + {sfHookInstructionCost, soeOPTIONAL}}); add(sfHookEmission.jsonName.c_str(), sfHookEmission.getCode(), @@ -91,7 +92,7 @@ InnerObjectFormats::InnerObjectFormats() {sfHookCanEmit, soeOPTIONAL}, {sfHookApiVersion, soeREQUIRED}, {sfFlags, soeREQUIRED}, - {sfFee, soeREQUIRED}}); + {sfFee, soeOPTIONAL}}); add(sfHook.jsonName.c_str(), sfHook.getCode(), diff --git a/src/ripple/protocol/impl/SField.cpp b/src/ripple/protocol/impl/SField.cpp index c4f2ef85a..813658df3 100644 --- a/src/ripple/protocol/impl/SField.cpp +++ b/src/ripple/protocol/impl/SField.cpp @@ -158,6 +158,10 @@ CONSTRUCT_TYPED_SFIELD(sfLockCount, "LockCount", UINT32, CONSTRUCT_TYPED_SFIELD(sfFirstNFTokenSequence, "FirstNFTokenSequence", UINT32, 50); +// 32-bit integers (hook) +CONSTRUCT_TYPED_SFIELD(sfHookInstructionCost, "HookInstructionCost", UINT32, 91); +CONSTRUCT_TYPED_SFIELD(sfHookGas, "HookGas", UINT32, 92); + CONSTRUCT_TYPED_SFIELD(sfStartTime, "StartTime", UINT32, 93); CONSTRUCT_TYPED_SFIELD(sfRepeatCount, "RepeatCount", UINT32, 94); CONSTRUCT_TYPED_SFIELD(sfDelaySeconds, "DelaySeconds", UINT32, 95); @@ -270,6 +274,7 @@ CONSTRUCT_TYPED_SFIELD(sfBaseFeeDrops, "BaseFeeDrops", AMOU CONSTRUCT_TYPED_SFIELD(sfReserveBaseDrops, "ReserveBaseDrops", AMOUNT, 23); CONSTRUCT_TYPED_SFIELD(sfReserveIncrementDrops, "ReserveIncrementDrops", AMOUNT, 24); + // variable length (common) CONSTRUCT_TYPED_SFIELD(sfPublicKey, "PublicKey", VL, 1); CONSTRUCT_TYPED_SFIELD(sfMessageKey, "MessageKey", VL, 2); diff --git a/src/ripple/protocol/impl/TER.cpp b/src/ripple/protocol/impl/TER.cpp index 08992c6a3..654a93fe8 100644 --- a/src/ripple/protocol/impl/TER.cpp +++ b/src/ripple/protocol/impl/TER.cpp @@ -95,6 +95,7 @@ transResults() MAKE_ERROR(tecIMMUTABLE, "The remark is marked immutable on the object, and therefore cannot be updated."), MAKE_ERROR(tecTOO_MANY_REMARKS, "The number of remarks on the object would exceed the limit of 32."), MAKE_ERROR(tecHAS_HOOK_STATE, "Delete all hook state before reducing scale"), + MAKE_ERROR(tecHOOK_INSUFFICIENT_GAS, "Insufficient hook gas to complete the transaction."), MAKE_ERROR(tefALREADY, "The exact transaction was already in this ledger."), MAKE_ERROR(tefBAD_ADD_AUTH, "Not authorized to add account."), diff --git a/src/ripple/protocol/impl/TxFormats.cpp b/src/ripple/protocol/impl/TxFormats.cpp index 789de36f2..87162f55e 100644 --- a/src/ripple/protocol/impl/TxFormats.cpp +++ b/src/ripple/protocol/impl/TxFormats.cpp @@ -44,6 +44,7 @@ TxFormats::TxFormats() {sfNetworkID, soeOPTIONAL}, {sfHookParameters, soeOPTIONAL}, {sfOperationLimit, soeOPTIONAL}, + {sfHookGas, soeOPTIONAL}, }; add(jss::AccountSet, diff --git a/src/test/app/SetHook_test.cpp b/src/test/app/SetHook_test.cpp index 0c7be29e8..398a06b73 100644 --- a/src/test/app/SetHook_test.cpp +++ b/src/test/app/SetHook_test.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #include namespace ripple { @@ -13377,9 +13378,237 @@ public: } } + void + testGasTypeHookDisabled(FeatureBitset features) + { + testcase("Test Gas-type Hook disabled"); + using namespace jtx; + Env env{*this, features - featureHookGas}; + auto const alice = Account{"alice"}; + env.fund(XRP(10000), alice); + env.close(); + + // Install a Gas-type hook with Version 1 + Json::Value jvh = hso(gas_accept_wasm, overrideFlag); + jvh[jss::HookApiVersion] = 0; + + env(ripple::test::jtx::hook(alice, {{jvh}}, 0), + M("test gas type hook installation"), + HSFEE, + ter(temMALFORMED)); + + // Install a Gas-type hook with Version 1 + jvh[jss::HookApiVersion] = 1; + + env(ripple::test::jtx::hook(alice, {{jvh}}, 0), + M("test gas type hook installation"), + HSFEE, + ter(temMALFORMED)); + + // HookGas field + env(invoke::invoke(alice), + hookgas(1000000), + M("test gas type hook invocation"), + fee(XRP(1)), + ter(temMALFORMED)); + env.close(); + } + + void + testGasTypeHookInstallation(FeatureBitset features) + { + testcase("Test Gas-type Hook installation"); + using namespace jtx; + + Env env{*this, features}; + auto const alice = Account{"alice"}; + env.fund(XRP(10000), alice); + env.close(); + + // Install a Gas-type hook using gas_accept_wasm + Json::Value jvh = hso(gas_accept_wasm, overrideFlag); + jvh[jss::HookApiVersion] = 1; + + env(ripple::test::jtx::hook(alice, {{jvh}}, 0), + M("test gas type hook installation"), + HSFEE); + env.close(); + + // no HookGas field for Gas-type hook + env(invoke::invoke(alice), + M("test gas type hook invocation"), + fee(XRP(1)), + ter(tecHOOK_INSUFFICIENT_GAS)); + env.close(); + + // insufficient fee for gas type hook + // baseFee + HookGas fee + gas type Hook call fee + auto const expectedGas = 1'000'000; + auto const expectedFee = + env.current()->fees().base + drops(expectedGas) + drops(200'000); + env(invoke::invoke(alice), + hookgas(expectedGas), + fee(expectedFee - drops(1)), + ter(telINSUF_FEE_P)); + env.close(); + + // HookGas field for Gas-type hook + env(invoke::invoke(alice), hookgas(expectedGas), fee(expectedFee)); + env.close(); + } + + void + testGasTypeHookRejects_gFunction(FeatureBitset features) + { + testcase("Test Gas-type Hook rejects _g function"); + using namespace jtx; + + Env env{*this, features}; + auto const alice = Account{"alice"}; + env.fund(XRP(10000), alice); + env.close(); + + // Attempt to install Gas-type hook with _g function (should fail) + Json::Value jv = hso(gas_with_g_wasm, overrideFlag); + jv[jss::HookApiVersion] = 1; + + env(ripple::test::jtx::hook(alice, {{jv}}, 0), + M("test gas type hook rejects _g function"), + HSFEE, + ter(temMALFORMED)); // Should fail because Gas-type + // hooks cannot use _g + env.close(); + } + + void + testGasExecutionSufficient(FeatureBitset features) + { + testcase("Test Gas execution with sufficient gas"); + using namespace jtx; + + Env env{*this, features}; + auto const alice = Account{"alice"}; + auto const bob = Account{"bob"}; + env.fund(XRP(100000), alice, bob); + env.close(); + + // Install Gas-type hook with sufficient gas + Json::Value jvh = hso(gas_long_wasm, overrideFlag); + jvh[jss::HookApiVersion] = 1; + + env(ripple::test::jtx::hook(alice, {{jvh}}, 0), HSFEE, ter(tesSUCCESS)); + env.close(); + + // Trigger the hook with a payment + env(pay(bob, alice, XRP(1)), + // insufficient gas for long execution + hookgas(100), + fee(XRP(10000)), + ter(tecHOOK_INSUFFICIENT_GAS)); + env.close(); + + // check exit type + auto meta = env.meta(); + BEAST_REQUIRE(meta); + BEAST_REQUIRE(meta->isFieldPresent(sfHookExecutions)); + + auto hookExecutions = meta->getFieldArray(sfHookExecutions); + BEAST_REQUIRE(hookExecutions.size() == 1); + + // validate HookInstructionCost + BEAST_REQUIRE(hookExecutions[0].isFieldPresent(sfHookInstructionCost)); + BEAST_REQUIRE( + hookExecutions[0].getFieldU32(sfHookInstructionCost) == 100); + // check exit type + BEAST_REQUIRE(hookExecutions[0].isFieldPresent(sfHookResult)); + BEAST_REQUIRE( + hookExecutions[0].getFieldU8(sfHookResult) == + hook_api::ExitType::WASM_ERROR); + + // Trigger the hook with a payment + env(pay(bob, alice, XRP(1)), + // Sufficient gas for long execution + hookgas(10000000), + fee(XRP(10000)), + ter(tesSUCCESS)); + env.close(); + + meta = env.meta(); + BEAST_REQUIRE(meta); + BEAST_REQUIRE(meta->isFieldPresent(sfHookExecutions)); + + hookExecutions = meta->getFieldArray(sfHookExecutions); + BEAST_REQUIRE(hookExecutions.size() == 1); + + // validate HookInstructionCost + BEAST_REQUIRE(hookExecutions[0].isFieldPresent(sfHookInstructionCost)); + BEAST_REQUIRE( + hookExecutions[0].getFieldU32(sfHookInstructionCost) == 2014); + // check exit type + BEAST_REQUIRE(hookExecutions[0].isFieldPresent(sfHookResult)); + BEAST_REQUIRE( + hookExecutions[0].getFieldU8(sfHookResult) == + hook_api::ExitType::ACCEPT); + } + + void + testMultipleGasHooksSharedPool(FeatureBitset features) + { + testcase("Test multiple Gas-type hooks share gas pool"); + using namespace jtx; + + Env env{*this, features}; + auto const alice = Account{"alice"}; + auto const bob = Account{"bob"}; + env.fund(XRP(100000), alice, bob); + env.close(); + + // Install multiple Gas-type hooks + // First hook + Json::Value hook1 = hso(gas_accept_wasm, overrideFlag); + hook1[jss::HookApiVersion] = 1; + + // Second hook + Json::Value hook2 = hso(gas_long_wasm, overrideFlag); + hook2[jss::HookApiVersion] = 1; + + env(ripple::test::jtx::hook(alice, {{hook1, hook2}}, 0), + M("test multiple gas hooks shared pool"), + HSFEE, + ter(tesSUCCESS)); + env.close(); + + // Trigger hooks with a payment + Json::Value jv = pay(bob, alice, XRP(1)); + env(jv, hookgas(10000000), fee(XRP(10000)), ter(tesSUCCESS)); + env.close(); + + auto meta = env.meta(); + BEAST_REQUIRE(meta); + BEAST_REQUIRE(meta->isFieldPresent(sfHookExecutions)); + + auto const hookExecutions = meta->getFieldArray(sfHookExecutions); + BEAST_REQUIRE(hookExecutions.size() == 2); + + // validate HookInstructionCost + BEAST_REQUIRE(hookExecutions[0].isFieldPresent(sfHookInstructionCost)); + BEAST_REQUIRE(hookExecutions[1].isFieldPresent(sfHookInstructionCost)); + BEAST_REQUIRE( + hookExecutions[0].getFieldU32(sfHookInstructionCost) == 14); + BEAST_REQUIRE( + hookExecutions[1].getFieldU32(sfHookInstructionCost) == 2014); + } + void testWithFeatures(FeatureBitset features) { + // Gas-type Hook tests + testGasTypeHookDisabled(features); + testGasTypeHookInstallation(features); + testGasTypeHookRejects_gFunction(features); + testGasExecutionSufficient(features); + testMultipleGasHooksSharedPool(features); + return; testHooksOwnerDir(features); testHooksDisabled(features); testTxStructure(features); @@ -13492,6 +13721,13 @@ public: test_util_raddr(features); // test_util_sha512h(features); // test_util_verify(features); // + + // Gas-type Hook tests + testGasTypeHookDisabled(features); + testGasTypeHookInstallation(features); + testGasTypeHookRejects_gFunction(features); + testGasExecutionSufficient(features); + testMultipleGasHooksSharedPool(features); } public: @@ -13662,6 +13898,53 @@ private: )[test.hook]"]; HASH_WASM(accept2); + + TestHook gas_accept_wasm = // WASM: 7 + wasm[ + R"[test.hook.gas]( + #include + extern int64_t accept (uint32_t read_ptr, uint32_t read_len, int64_t error_code); + int64_t hook(uint32_t reserved ) + { + return accept(0,0,0); + } + )[test.hook.gas]"]; + + HASH_WASM(gas_accept); + + TestHook gas_with_g_wasm = // WASM: 8 + wasm[ + R"[test.hook.gas]( + #include + extern int32_t _g (uint32_t id, uint32_t maxiter); + extern int64_t accept (uint32_t read_ptr, uint32_t read_len, int64_t error_code); + int64_t hook(uint32_t reserved ) + { + _g(1,1); + return accept(0,0,0); + } + )[test.hook.gas]"]; + + HASH_WASM(gas_with_g); + + TestHook gas_long_wasm = // WASM: 9 + wasm[ + R"[test.hook.gas]( + #include + extern int64_t accept (uint32_t read_ptr, uint32_t read_len, int64_t error_code); + extern int64_t float_one(); + #define SBUF(x) (uint32_t)(x), sizeof(x) + #define M_REPEAT_10(X) X X X X X X X X X X + #define M_REPEAT_100(X) M_REPEAT_10(M_REPEAT_10(X)) + #define M_REPEAT_1000(X) M_REPEAT_100(M_REPEAT_10(X)) + int64_t hook(uint32_t reserved ) + { + M_REPEAT_1000(float_one();); + return accept(0, 0, 0); + } + )[test.hook.gas]"]; + + HASH_WASM(gas_long); }; #define SETHOOK_TEST(i, last) \ diff --git a/src/test/app/SetHook_wasm.h b/src/test/app/SetHook_wasm.h index 73294c9fb..23a671027 100644 --- a/src/test/app/SetHook_wasm.h +++ b/src/test/app/SetHook_wasm.h @@ -16805,7 +16805,7 @@ std::map> wasm = { 0x64U, 0xE1U, 0xF1U, }}, - /* ==== WASM: 79 ==== */ + /* ==== WASM: 80 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -16978,7 +16978,7 @@ std::map> wasm = { 0x54U, 0x5FU, 0x45U, 0x58U, 0x49U, 0x53U, 0x54U, 0x00U, }}, - /* ==== WASM: 80 ==== */ + /* ==== WASM: 81 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -17126,7 +17126,7 @@ std::map> wasm = { 0x30U, 0x00U, 0x22U, 0x00U, 0x00U, 0x00U, 0x00U, }}, - /* ==== WASM: 81 ==== */ + /* ==== WASM: 82 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -17223,7 +17223,7 @@ std::map> wasm = { 0x3DU, 0x20U, 0x30U, 0x00U, }}, - /* ==== WASM: 82 ==== */ + /* ==== WASM: 83 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -17282,7 +17282,7 @@ std::map> wasm = { 0x4FU, 0x46U, 0x5FU, 0x42U, 0x4FU, 0x55U, 0x4EU, 0x44U, 0x53U, 0x00U, }}, - /* ==== WASM: 83 ==== */ + /* ==== WASM: 84 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -17341,7 +17341,7 @@ std::map> wasm = { 0x4EU, 0x44U, 0x53U, 0x00U, }}, - /* ==== WASM: 84 ==== */ + /* ==== WASM: 85 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -19170,7 +19170,7 @@ std::map> wasm = { 0x53U, 0x4DU, 0x41U, 0x4CU, 0x4CU, 0x00U, }}, - /* ==== WASM: 85 ==== */ + /* ==== WASM: 86 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -20512,7 +20512,7 @@ std::map> wasm = { 0x20U, 0x30U, 0x2CU, 0x20U, 0x30U, 0x29U, 0x29U, 0x00U, }}, - /* ==== WASM: 86 ==== */ + /* ==== WASM: 87 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -23445,7 +23445,7 @@ std::map> wasm = { 0x4FU, 0x4FU, 0x5FU, 0x53U, 0x4DU, 0x41U, 0x4CU, 0x4CU, 0x00U, }}, - /* ==== WASM: 87 ==== */ + /* ==== WASM: 88 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -25410,7 +25410,7 @@ std::map> wasm = { 0x54U, 0x4FU, 0x4FU, 0x5FU, 0x53U, 0x4DU, 0x41U, 0x4CU, 0x4CU, 0x00U, }}, - /* ==== WASM: 88 ==== */ + /* ==== WASM: 89 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -25695,7 +25695,7 @@ std::map> wasm = { 0x29U, 0x20U, 0x3DU, 0x3DU, 0x20U, 0x30U, 0x00U, }}, - /* ==== WASM: 89 ==== */ + /* ==== WASM: 90 ==== */ {R"[test.hook]( #include extern int32_t _g(uint32_t, uint32_t); @@ -26282,7 +26282,7 @@ std::map> wasm = { 0x4EU, 0x5FU, 0x46U, 0x41U, 0x49U, 0x4CU, 0x55U, 0x52U, 0x45U, 0x00U, }}, - /* ==== WASM: 90 ==== */ + /* ==== WASM: 91 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -26311,7 +26311,7 @@ std::map> wasm = { 0x0BU, }}, - /* ==== WASM: 91 ==== */ + /* ==== WASM: 92 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -26343,7 +26343,7 @@ std::map> wasm = { 0x20U, 0x52U, 0x65U, 0x6AU, 0x65U, 0x63U, 0x74U, 0x65U, 0x64U, 0x00U, }}, - /* ==== WASM: 92 ==== */ + /* ==== WASM: 93 ==== */ {R"[test.hook]( (module (type (;0;) (func (param i32 i32 i64) (result i64))) @@ -26370,7 +26370,7 @@ std::map> wasm = { 0x41U, 0x00U, 0x41U, 0x00U, 0x42U, 0x00U, 0x10U, 0x00U, 0x0BU, }}, - /* ==== WASM: 93 ==== */ + /* ==== WASM: 94 ==== */ {R"[test.hook]( (module (type (;0;) (func (param i32 i32) (result i32))) @@ -26423,7 +26423,7 @@ std::map> wasm = { 0x00U, 0x1AU, 0x0BU, }}, - /* ==== WASM: 94 ==== */ + /* ==== WASM: 95 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -33066,7 +33066,7 @@ std::map> wasm = { 0x39U, 0x30U, 0x31U, 0x32U, 0x33U, 0x00U, }}, - /* ==== WASM: 95 ==== */ + /* ==== WASM: 96 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -33112,7 +33112,7 @@ std::map> wasm = { 0x0BU, 0x06U, 0x76U, 0x61U, 0x6CU, 0x75U, 0x65U, 0x00U, }}, - /* ==== WASM: 96 ==== */ + /* ==== WASM: 97 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -33141,6 +33141,870 @@ std::map> wasm = { 0x0BU, }}, + /* ==== WASM: 98 ==== */ + {R"[test.hook.gas]( + #include + extern int64_t accept (uint32_t read_ptr, uint32_t read_len, int64_t error_code); + int64_t hook(uint32_t reserved ) + { + return accept(0,0,0); + } + )[test.hook.gas]", + { + 0x00U, 0x61U, 0x73U, 0x6DU, 0x01U, 0x00U, 0x00U, 0x00U, 0x01U, 0x10U, + 0x03U, 0x60U, 0x03U, 0x7FU, 0x7FU, 0x7EU, 0x01U, 0x7EU, 0x60U, 0x00U, + 0x00U, 0x60U, 0x01U, 0x7FU, 0x01U, 0x7EU, 0x02U, 0x0EU, 0x01U, 0x03U, + 0x65U, 0x6EU, 0x76U, 0x06U, 0x61U, 0x63U, 0x63U, 0x65U, 0x70U, 0x74U, + 0x00U, 0x00U, 0x03U, 0x03U, 0x02U, 0x01U, 0x02U, 0x04U, 0x05U, 0x01U, + 0x70U, 0x01U, 0x01U, 0x01U, 0x05U, 0x03U, 0x01U, 0x00U, 0x02U, 0x06U, + 0x21U, 0x05U, 0x7FU, 0x01U, 0x41U, 0x80U, 0x88U, 0x04U, 0x0BU, 0x7FU, + 0x00U, 0x41U, 0x80U, 0x08U, 0x0BU, 0x7FU, 0x00U, 0x41U, 0x80U, 0x08U, + 0x0BU, 0x7FU, 0x00U, 0x41U, 0x80U, 0x88U, 0x04U, 0x0BU, 0x7FU, 0x00U, + 0x41U, 0x80U, 0x08U, 0x0BU, 0x07U, 0x5FU, 0x07U, 0x06U, 0x6DU, 0x65U, + 0x6DU, 0x6FU, 0x72U, 0x79U, 0x02U, 0x00U, 0x11U, 0x5FU, 0x5FU, 0x77U, + 0x61U, 0x73U, 0x6DU, 0x5FU, 0x63U, 0x61U, 0x6CU, 0x6CU, 0x5FU, 0x63U, + 0x74U, 0x6FU, 0x72U, 0x73U, 0x00U, 0x01U, 0x0AU, 0x5FU, 0x5FU, 0x64U, + 0x61U, 0x74U, 0x61U, 0x5FU, 0x65U, 0x6EU, 0x64U, 0x03U, 0x01U, 0x0DU, + 0x5FU, 0x5FU, 0x67U, 0x6CU, 0x6FU, 0x62U, 0x61U, 0x6CU, 0x5FU, 0x62U, + 0x61U, 0x73U, 0x65U, 0x03U, 0x02U, 0x0BU, 0x5FU, 0x5FU, 0x68U, 0x65U, + 0x61U, 0x70U, 0x5FU, 0x62U, 0x61U, 0x73U, 0x65U, 0x03U, 0x03U, 0x0CU, + 0x5FU, 0x5FU, 0x64U, 0x73U, 0x6FU, 0x5FU, 0x68U, 0x61U, 0x6EU, 0x64U, + 0x6CU, 0x65U, 0x03U, 0x04U, 0x04U, 0x68U, 0x6FU, 0x6FU, 0x6BU, 0x00U, + 0x02U, 0x0AU, 0x13U, 0x02U, 0x02U, 0x00U, 0x0BU, 0x0EU, 0x00U, 0x41U, + 0x00U, 0x41U, 0x00U, 0x42U, 0x00U, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, + 0x00U, 0x0BU, 0x00U, 0x29U, 0x04U, 0x6EU, 0x61U, 0x6DU, 0x65U, 0x01U, + 0x22U, 0x03U, 0x00U, 0x06U, 0x61U, 0x63U, 0x63U, 0x65U, 0x70U, 0x74U, + 0x01U, 0x11U, 0x5FU, 0x5FU, 0x77U, 0x61U, 0x73U, 0x6DU, 0x5FU, 0x63U, + 0x61U, 0x6CU, 0x6CU, 0x5FU, 0x63U, 0x74U, 0x6FU, 0x72U, 0x73U, 0x02U, + 0x04U, 0x68U, 0x6FU, 0x6FU, 0x6BU, 0x00U, 0x75U, 0x09U, 0x70U, 0x72U, + 0x6FU, 0x64U, 0x75U, 0x63U, 0x65U, 0x72U, 0x73U, 0x01U, 0x0CU, 0x70U, + 0x72U, 0x6FU, 0x63U, 0x65U, 0x73U, 0x73U, 0x65U, 0x64U, 0x2DU, 0x62U, + 0x79U, 0x01U, 0x05U, 0x63U, 0x6CU, 0x61U, 0x6EU, 0x67U, 0x55U, 0x39U, + 0x2EU, 0x30U, 0x2EU, 0x30U, 0x20U, 0x28U, 0x68U, 0x74U, 0x74U, 0x70U, + 0x73U, 0x3AU, 0x2FU, 0x2FU, 0x67U, 0x69U, 0x74U, 0x68U, 0x75U, 0x62U, + 0x2EU, 0x63U, 0x6FU, 0x6DU, 0x2FU, 0x6CU, 0x6CU, 0x76U, 0x6DU, 0x2FU, + 0x6CU, 0x6CU, 0x76U, 0x6DU, 0x2DU, 0x70U, 0x72U, 0x6FU, 0x6AU, 0x65U, + 0x63U, 0x74U, 0x20U, 0x30U, 0x33U, 0x39U, 0x39U, 0x64U, 0x35U, 0x61U, + 0x39U, 0x36U, 0x38U, 0x32U, 0x62U, 0x33U, 0x63U, 0x65U, 0x66U, 0x37U, + 0x31U, 0x63U, 0x36U, 0x35U, 0x33U, 0x33U, 0x37U, 0x33U, 0x65U, 0x33U, + 0x38U, 0x38U, 0x39U, 0x30U, 0x63U, 0x36U, 0x33U, 0x63U, 0x34U, 0x63U, + 0x33U, 0x36U, 0x35U, 0x29U, + }}, + + /* ==== WASM: 99 ==== */ + {R"[test.hook.gas]( + #include + extern int32_t _g (uint32_t id, uint32_t maxiter); + extern int64_t accept (uint32_t read_ptr, uint32_t read_len, int64_t error_code); + int64_t hook(uint32_t reserved ) + { + _g(1,1); + return accept(0,0,0); + } + )[test.hook.gas]", + { + 0x00U, 0x61U, 0x73U, 0x6DU, 0x01U, 0x00U, 0x00U, 0x00U, 0x01U, 0x16U, + 0x04U, 0x60U, 0x02U, 0x7FU, 0x7FU, 0x01U, 0x7FU, 0x60U, 0x03U, 0x7FU, + 0x7FU, 0x7EU, 0x01U, 0x7EU, 0x60U, 0x00U, 0x00U, 0x60U, 0x01U, 0x7FU, + 0x01U, 0x7EU, 0x02U, 0x17U, 0x02U, 0x03U, 0x65U, 0x6EU, 0x76U, 0x02U, + 0x5FU, 0x67U, 0x00U, 0x00U, 0x03U, 0x65U, 0x6EU, 0x76U, 0x06U, 0x61U, + 0x63U, 0x63U, 0x65U, 0x70U, 0x74U, 0x00U, 0x01U, 0x03U, 0x03U, 0x02U, + 0x02U, 0x03U, 0x04U, 0x05U, 0x01U, 0x70U, 0x01U, 0x01U, 0x01U, 0x05U, + 0x03U, 0x01U, 0x00U, 0x02U, 0x06U, 0x21U, 0x05U, 0x7FU, 0x01U, 0x41U, + 0x80U, 0x88U, 0x04U, 0x0BU, 0x7FU, 0x00U, 0x41U, 0x80U, 0x08U, 0x0BU, + 0x7FU, 0x00U, 0x41U, 0x80U, 0x08U, 0x0BU, 0x7FU, 0x00U, 0x41U, 0x80U, + 0x88U, 0x04U, 0x0BU, 0x7FU, 0x00U, 0x41U, 0x80U, 0x08U, 0x0BU, 0x07U, + 0x5FU, 0x07U, 0x06U, 0x6DU, 0x65U, 0x6DU, 0x6FU, 0x72U, 0x79U, 0x02U, + 0x00U, 0x11U, 0x5FU, 0x5FU, 0x77U, 0x61U, 0x73U, 0x6DU, 0x5FU, 0x63U, + 0x61U, 0x6CU, 0x6CU, 0x5FU, 0x63U, 0x74U, 0x6FU, 0x72U, 0x73U, 0x00U, + 0x02U, 0x0AU, 0x5FU, 0x5FU, 0x64U, 0x61U, 0x74U, 0x61U, 0x5FU, 0x65U, + 0x6EU, 0x64U, 0x03U, 0x01U, 0x0DU, 0x5FU, 0x5FU, 0x67U, 0x6CU, 0x6FU, + 0x62U, 0x61U, 0x6CU, 0x5FU, 0x62U, 0x61U, 0x73U, 0x65U, 0x03U, 0x02U, + 0x0BU, 0x5FU, 0x5FU, 0x68U, 0x65U, 0x61U, 0x70U, 0x5FU, 0x62U, 0x61U, + 0x73U, 0x65U, 0x03U, 0x03U, 0x0CU, 0x5FU, 0x5FU, 0x64U, 0x73U, 0x6FU, + 0x5FU, 0x68U, 0x61U, 0x6EU, 0x64U, 0x6CU, 0x65U, 0x03U, 0x04U, 0x04U, + 0x68U, 0x6FU, 0x6FU, 0x6BU, 0x00U, 0x03U, 0x0AU, 0x1EU, 0x02U, 0x02U, + 0x00U, 0x0BU, 0x19U, 0x00U, 0x41U, 0x01U, 0x41U, 0x01U, 0x10U, 0x80U, + 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x41U, 0x00U, 0x41U, 0x00U, 0x42U, + 0x00U, 0x10U, 0x81U, 0x80U, 0x80U, 0x80U, 0x00U, 0x0BU, 0x00U, 0x2DU, + 0x04U, 0x6EU, 0x61U, 0x6DU, 0x65U, 0x01U, 0x26U, 0x04U, 0x00U, 0x02U, + 0x5FU, 0x67U, 0x01U, 0x06U, 0x61U, 0x63U, 0x63U, 0x65U, 0x70U, 0x74U, + 0x02U, 0x11U, 0x5FU, 0x5FU, 0x77U, 0x61U, 0x73U, 0x6DU, 0x5FU, 0x63U, + 0x61U, 0x6CU, 0x6CU, 0x5FU, 0x63U, 0x74U, 0x6FU, 0x72U, 0x73U, 0x03U, + 0x04U, 0x68U, 0x6FU, 0x6FU, 0x6BU, 0x00U, 0x75U, 0x09U, 0x70U, 0x72U, + 0x6FU, 0x64U, 0x75U, 0x63U, 0x65U, 0x72U, 0x73U, 0x01U, 0x0CU, 0x70U, + 0x72U, 0x6FU, 0x63U, 0x65U, 0x73U, 0x73U, 0x65U, 0x64U, 0x2DU, 0x62U, + 0x79U, 0x01U, 0x05U, 0x63U, 0x6CU, 0x61U, 0x6EU, 0x67U, 0x55U, 0x39U, + 0x2EU, 0x30U, 0x2EU, 0x30U, 0x20U, 0x28U, 0x68U, 0x74U, 0x74U, 0x70U, + 0x73U, 0x3AU, 0x2FU, 0x2FU, 0x67U, 0x69U, 0x74U, 0x68U, 0x75U, 0x62U, + 0x2EU, 0x63U, 0x6FU, 0x6DU, 0x2FU, 0x6CU, 0x6CU, 0x76U, 0x6DU, 0x2FU, + 0x6CU, 0x6CU, 0x76U, 0x6DU, 0x2DU, 0x70U, 0x72U, 0x6FU, 0x6AU, 0x65U, + 0x63U, 0x74U, 0x20U, 0x30U, 0x33U, 0x39U, 0x39U, 0x64U, 0x35U, 0x61U, + 0x39U, 0x36U, 0x38U, 0x32U, 0x62U, 0x33U, 0x63U, 0x65U, 0x66U, 0x37U, + 0x31U, 0x63U, 0x36U, 0x35U, 0x33U, 0x33U, 0x37U, 0x33U, 0x65U, 0x33U, + 0x38U, 0x38U, 0x39U, 0x30U, 0x63U, 0x36U, 0x33U, 0x63U, 0x34U, 0x63U, + 0x33U, 0x36U, 0x35U, 0x29U, + }}, + + /* ==== WASM: 100 ==== */ + {R"[test.hook.gas]( + #include + extern int64_t accept (uint32_t read_ptr, uint32_t read_len, int64_t error_code); + extern int64_t float_one(); + #define SBUF(x) (uint32_t)(x), sizeof(x) + #define M_REPEAT_10(X) X X X X X X X X X X + #define M_REPEAT_100(X) M_REPEAT_10(M_REPEAT_10(X)) + #define M_REPEAT_1000(X) M_REPEAT_100(M_REPEAT_10(X)) + int64_t hook(uint32_t reserved ) + { + M_REPEAT_1000(float_one();); + return accept(0, 0, 0); + } + )[test.hook.gas]", + { + 0x00U, 0x61U, 0x73U, 0x6DU, 0x01U, 0x00U, 0x00U, 0x00U, 0x01U, 0x14U, + 0x04U, 0x60U, 0x00U, 0x01U, 0x7EU, 0x60U, 0x03U, 0x7FU, 0x7FU, 0x7EU, + 0x01U, 0x7EU, 0x60U, 0x00U, 0x00U, 0x60U, 0x01U, 0x7FU, 0x01U, 0x7EU, + 0x02U, 0x1EU, 0x02U, 0x03U, 0x65U, 0x6EU, 0x76U, 0x09U, 0x66U, 0x6CU, + 0x6FU, 0x61U, 0x74U, 0x5FU, 0x6FU, 0x6EU, 0x65U, 0x00U, 0x00U, 0x03U, + 0x65U, 0x6EU, 0x76U, 0x06U, 0x61U, 0x63U, 0x63U, 0x65U, 0x70U, 0x74U, + 0x00U, 0x01U, 0x03U, 0x03U, 0x02U, 0x02U, 0x03U, 0x04U, 0x05U, 0x01U, + 0x70U, 0x01U, 0x01U, 0x01U, 0x05U, 0x03U, 0x01U, 0x00U, 0x02U, 0x06U, + 0x21U, 0x05U, 0x7FU, 0x01U, 0x41U, 0x80U, 0x88U, 0x04U, 0x0BU, 0x7FU, + 0x00U, 0x41U, 0x80U, 0x08U, 0x0BU, 0x7FU, 0x00U, 0x41U, 0x80U, 0x08U, + 0x0BU, 0x7FU, 0x00U, 0x41U, 0x80U, 0x88U, 0x04U, 0x0BU, 0x7FU, 0x00U, + 0x41U, 0x80U, 0x08U, 0x0BU, 0x07U, 0x5FU, 0x07U, 0x06U, 0x6DU, 0x65U, + 0x6DU, 0x6FU, 0x72U, 0x79U, 0x02U, 0x00U, 0x11U, 0x5FU, 0x5FU, 0x77U, + 0x61U, 0x73U, 0x6DU, 0x5FU, 0x63U, 0x61U, 0x6CU, 0x6CU, 0x5FU, 0x63U, + 0x74U, 0x6FU, 0x72U, 0x73U, 0x00U, 0x02U, 0x0AU, 0x5FU, 0x5FU, 0x64U, + 0x61U, 0x74U, 0x61U, 0x5FU, 0x65U, 0x6EU, 0x64U, 0x03U, 0x01U, 0x0DU, + 0x5FU, 0x5FU, 0x67U, 0x6CU, 0x6FU, 0x62U, 0x61U, 0x6CU, 0x5FU, 0x62U, + 0x61U, 0x73U, 0x65U, 0x03U, 0x02U, 0x0BU, 0x5FU, 0x5FU, 0x68U, 0x65U, + 0x61U, 0x70U, 0x5FU, 0x62U, 0x61U, 0x73U, 0x65U, 0x03U, 0x03U, 0x0CU, + 0x5FU, 0x5FU, 0x64U, 0x73U, 0x6FU, 0x5FU, 0x68U, 0x61U, 0x6EU, 0x64U, + 0x6CU, 0x65U, 0x03U, 0x04U, 0x04U, 0x68U, 0x6FU, 0x6FU, 0x6BU, 0x00U, + 0x03U, 0x0AU, 0xECU, 0x36U, 0x02U, 0x02U, 0x00U, 0x0BU, 0xE6U, 0x36U, + 0x00U, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, + 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, + 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, + 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, + 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, + 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, + 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, + 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, + 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, + 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, + 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, + 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, + 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, + 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, + 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, + 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, + 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, + 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, + 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, + 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, + 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, + 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, + 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, + 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, + 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, + 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, + 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, + 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, + 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, + 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, + 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, + 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, + 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, + 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, + 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, + 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, + 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, + 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, + 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, + 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, + 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, + 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, + 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, + 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, + 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, + 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, + 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, + 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, + 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, + 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, + 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, + 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, + 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, + 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, + 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, + 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, + 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, + 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, + 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, + 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, + 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, + 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, + 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, + 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, + 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, + 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, + 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, + 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, + 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, + 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, + 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, + 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, + 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, + 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, + 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, + 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, + 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, + 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, + 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, + 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, + 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, + 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, + 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, + 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, + 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, + 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, + 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, + 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, + 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, + 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, + 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, + 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, + 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, + 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, + 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, + 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, + 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, + 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, + 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, + 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, + 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, + 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, + 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, + 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, + 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, + 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, + 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, + 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, + 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, + 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, + 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, + 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, + 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, + 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, + 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, + 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, + 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, + 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, + 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, + 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, + 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, + 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, + 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, + 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, + 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, + 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, + 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, + 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, + 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, + 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, + 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, + 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, + 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, + 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, + 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, + 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, + 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, + 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, + 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, + 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, + 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, + 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, + 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, + 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, + 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, + 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, + 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, + 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, + 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, + 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, + 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, + 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, + 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, + 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, + 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, + 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, + 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, + 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, + 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, + 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, + 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, + 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, + 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, + 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, + 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, + 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, + 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, + 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, + 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, + 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, + 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, + 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, + 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, + 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, + 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, + 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, + 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, + 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, + 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, + 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, + 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, + 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, + 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, + 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, + 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, + 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, + 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, + 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, + 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, + 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, + 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, + 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, + 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, + 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, + 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, + 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, + 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, + 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, + 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, + 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, + 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, + 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, + 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, + 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, + 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, + 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, + 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, + 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, + 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, + 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, + 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, + 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, + 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, + 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, + 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, + 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, + 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, + 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, + 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, + 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, + 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, + 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, + 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, + 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, + 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, + 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, + 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, + 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, + 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, + 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, + 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, + 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, + 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, + 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, + 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, + 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, + 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, + 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, + 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, + 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, + 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, + 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, + 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, + 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, + 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, + 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, + 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, + 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, + 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, + 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, + 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, + 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, + 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, + 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, + 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, + 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, + 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, + 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, + 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, + 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, + 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, + 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, + 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, + 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, + 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, + 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, + 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, + 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, + 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, + 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, + 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, + 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, + 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, + 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, + 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, + 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, + 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, + 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, + 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, + 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, + 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, + 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, + 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, + 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, + 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, + 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, + 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, + 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, + 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, + 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, + 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, + 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, + 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, + 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, + 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, + 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, + 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, + 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, + 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, + 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, + 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, + 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, + 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, + 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, + 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, + 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, + 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, + 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, + 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, + 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, + 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, + 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, + 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, + 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, + 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, + 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, + 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, + 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, + 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, + 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, + 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, + 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, + 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, + 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, + 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, + 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, + 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, + 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, + 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, + 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, + 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, + 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, + 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, + 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, + 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, + 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, + 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, + 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, + 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, + 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, + 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, + 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, + 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, + 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, + 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, + 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, + 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, + 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, + 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, + 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, + 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, + 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, + 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, + 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, + 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, + 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, + 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, + 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, + 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, + 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, + 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, + 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, + 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, + 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, + 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, + 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, + 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, + 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, + 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, + 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, + 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, + 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, + 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, + 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, + 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, + 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, + 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, + 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, + 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, + 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, + 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, + 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, + 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, + 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, + 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, + 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, + 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, + 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, + 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, + 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, + 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, + 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, + 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, + 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, + 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, + 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, + 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, + 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, + 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, + 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, + 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, + 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, + 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, + 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, + 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, + 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, + 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, + 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, + 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, + 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, + 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, + 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, + 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, + 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, + 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, + 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, + 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, + 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, + 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, + 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, + 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, + 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, + 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, + 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, + 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, + 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, + 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, + 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, + 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, + 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, + 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, + 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, + 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, + 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, + 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, + 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, + 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, + 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, + 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, + 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, + 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, + 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, + 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, + 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, + 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, + 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, + 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, + 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, + 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, + 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, + 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, + 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, + 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, + 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, + 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, + 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, + 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, + 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, + 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, + 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, + 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, + 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, + 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, + 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, + 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, + 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, + 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, + 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, + 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, + 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, + 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, + 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, + 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, + 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, + 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, + 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, + 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, + 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, + 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, + 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, + 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, + 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, + 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, + 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, + 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, + 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, + 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, + 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, + 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, + 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, + 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, + 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, + 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, + 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, + 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, + 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, + 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, + 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, + 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, + 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, + 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, + 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, + 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, + 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, + 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, + 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, + 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, + 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, + 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, + 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, + 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, + 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, + 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, + 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, + 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, + 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, + 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, + 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, + 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, + 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, + 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, + 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, + 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, + 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, + 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, + 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, + 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, + 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, + 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, + 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, + 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, + 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, + 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, + 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, + 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, + 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, + 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, + 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, + 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, + 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, + 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, + 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, + 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, + 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, + 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, + 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, + 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, + 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, + 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, + 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, + 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, + 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, + 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, + 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, + 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, + 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, + 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, + 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, + 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, + 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, + 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, + 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, + 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, + 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, + 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, + 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, + 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, + 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, + 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, + 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, + 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, + 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, + 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, + 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, + 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, + 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, + 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, + 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, + 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, + 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, + 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, + 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, + 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, + 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, + 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, + 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, + 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, + 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, + 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, + 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, + 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, + 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, + 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, + 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, + 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, + 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, + 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, + 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, + 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, + 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, + 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, + 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, + 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, + 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, + 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, + 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, + 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, + 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, + 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, + 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, + 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, + 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, + 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, + 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, + 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, + 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, + 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, + 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, + 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, + 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, + 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, + 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, + 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, + 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, + 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, + 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, + 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, + 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, + 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, + 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, + 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, + 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, + 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, + 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, + 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, + 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, + 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, + 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, + 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, + 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, + 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, + 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, + 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, + 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, + 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, + 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, + 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, + 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, + 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, + 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, + 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, + 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, + 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, + 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, + 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, + 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, + 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, + 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, + 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, + 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, + 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, + 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, + 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, + 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, + 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, + 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, + 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, + 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, + 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, + 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, + 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, + 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, + 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, + 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, + 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, + 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, + 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, + 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, + 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, + 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, + 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, + 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, + 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, + 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, + 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, + 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, + 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, + 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, + 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, + 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, + 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, + 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, + 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, + 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, + 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, + 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, + 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, + 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, + 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, + 0x80U, 0x80U, 0x00U, 0x1AU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, + 0x1AU, 0x41U, 0x00U, 0x41U, 0x00U, 0x42U, 0x00U, 0x10U, 0x81U, 0x80U, + 0x80U, 0x80U, 0x00U, 0x0BU, 0x00U, 0x34U, 0x04U, 0x6EU, 0x61U, 0x6DU, + 0x65U, 0x01U, 0x2DU, 0x04U, 0x00U, 0x09U, 0x66U, 0x6CU, 0x6FU, 0x61U, + 0x74U, 0x5FU, 0x6FU, 0x6EU, 0x65U, 0x01U, 0x06U, 0x61U, 0x63U, 0x63U, + 0x65U, 0x70U, 0x74U, 0x02U, 0x11U, 0x5FU, 0x5FU, 0x77U, 0x61U, 0x73U, + 0x6DU, 0x5FU, 0x63U, 0x61U, 0x6CU, 0x6CU, 0x5FU, 0x63U, 0x74U, 0x6FU, + 0x72U, 0x73U, 0x03U, 0x04U, 0x68U, 0x6FU, 0x6FU, 0x6BU, 0x00U, 0x75U, + 0x09U, 0x70U, 0x72U, 0x6FU, 0x64U, 0x75U, 0x63U, 0x65U, 0x72U, 0x73U, + 0x01U, 0x0CU, 0x70U, 0x72U, 0x6FU, 0x63U, 0x65U, 0x73U, 0x73U, 0x65U, + 0x64U, 0x2DU, 0x62U, 0x79U, 0x01U, 0x05U, 0x63U, 0x6CU, 0x61U, 0x6EU, + 0x67U, 0x55U, 0x39U, 0x2EU, 0x30U, 0x2EU, 0x30U, 0x20U, 0x28U, 0x68U, + 0x74U, 0x74U, 0x70U, 0x73U, 0x3AU, 0x2FU, 0x2FU, 0x67U, 0x69U, 0x74U, + 0x68U, 0x75U, 0x62U, 0x2EU, 0x63U, 0x6FU, 0x6DU, 0x2FU, 0x6CU, 0x6CU, + 0x76U, 0x6DU, 0x2FU, 0x6CU, 0x6CU, 0x76U, 0x6DU, 0x2DU, 0x70U, 0x72U, + 0x6FU, 0x6AU, 0x65U, 0x63U, 0x74U, 0x20U, 0x30U, 0x33U, 0x39U, 0x39U, + 0x64U, 0x35U, 0x61U, 0x39U, 0x36U, 0x38U, 0x32U, 0x62U, 0x33U, 0x63U, + 0x65U, 0x66U, 0x37U, 0x31U, 0x63U, 0x36U, 0x35U, 0x33U, 0x33U, 0x37U, + 0x33U, 0x65U, 0x33U, 0x38U, 0x38U, 0x39U, 0x30U, 0x63U, 0x36U, 0x33U, + 0x63U, 0x34U, 0x63U, 0x33U, 0x36U, 0x35U, 0x29U, + }}, + }; } } // namespace ripple diff --git a/src/test/app/build_test_hooks.sh b/src/test/app/build_test_hooks.sh index 4e57701a8..8cad8cec7 100755 --- a/src/test/app/build_test_hooks.sh +++ b/src/test/app/build_test_hooks.sh @@ -41,17 +41,28 @@ echo ' namespace ripple { namespace test { std::map> wasm = {' > $OUTPUT_FILE -COUNTER="0" -cat $INPUT_FILE | tr '\n' '\f' | - grep -Po 'R"\[test\.hook\](.*?)\[test\.hook\]"' | - sed -E 's/R"\[test\.hook\]\(//g' | - sed -E 's/\)\[test\.hook\]"[\f \t]*/\/*end*\//g' | +# Counter file for sharing between subshells +COUNTER_FILE=$(mktemp) +echo "0" > $COUNTER_FILE +trap "rm -f $COUNTER_FILE" EXIT + +# Process both [test.hook] and [test.hook.gas] blocks +process_block() { + local tag_pattern="$1" # regex pattern: "hook" or "hook\.gas" + local tag_output="$2" # output string: "hook" or "hook.gas" + local skip_cleaner="$3" # "0" for no skip, "1" for skip + + cat $INPUT_FILE | tr '\n' '\f' | + grep -Po "R\"\[test\.${tag_pattern}\](.*?)\[test\.${tag_pattern}\]\"" | + sed -E "s/R\"\[test\.${tag_pattern}\]\(//g" | + sed -E "s/\)\[test\.${tag_pattern}\]\"[\f \t]*/\/*end*\//g" | while read -r line do + COUNTER=$(cat $COUNTER_FILE) echo "/* ==== WASM: $COUNTER ==== */" >> $OUTPUT_FILE - echo -n '{ R"[test.hook](' >> $OUTPUT_FILE + echo -n "{ R\"[test.${tag_output}](" >> $OUTPUT_FILE cat <<< "$line" | sed -E 's/.{7}$//g' | tr -d '\n' | tr '\f' '\n' >> $OUTPUT_FILE - echo ')[test.hook]",' >> $OUTPUT_FILE + echo ")[test.${tag_output}]\"," >> $OUTPUT_FILE echo "{" >> $OUTPUT_FILE WAT=`grep -Eo '\(module' <<< $line | wc -l` if [ "$WAT" -eq "0" ] @@ -69,10 +80,19 @@ cat $INPUT_FILE | tr '\n' '\f' | echo "$line" exit 1 fi - wasmcc -x c /dev/stdin -o /dev/stdout -O2 -Wl,--allow-undefined <<< "`tr '\f' '\n' <<< $line`" | - hook-cleaner - - 2>/dev/null | - xxd -p -u -c 10 | - sed -E 's/../0x&U,/g' | sed -E 's/^/ /g' >> $OUTPUT_FILE + if [ "$skip_cleaner" -eq "1" ] + then + # Skip hook-cleaner for [test.hook.gas] + wasmcc -x c /dev/stdin -o /dev/stdout -O2 -Wl,--allow-undefined <<< "`tr '\f' '\n' <<< $line`" | + xxd -p -u -c 10 | + sed -E 's/../0x&U,/g' | sed -E 's/^/ /g' >> $OUTPUT_FILE + else + # Run hook-cleaner for [test.hook] + wasmcc -x c /dev/stdin -o /dev/stdout -O2 -Wl,--allow-undefined <<< "`tr '\f' '\n' <<< $line`" | + hook-cleaner - - 2>/dev/null | + xxd -p -u -c 10 | + sed -E 's/../0x&U,/g' | sed -E 's/^/ /g' >> $OUTPUT_FILE + fi else wat2wasm - -o /dev/stdout <<< "`tr '\f' '\n' <<< $(sed -E 's/.{7}$//g' <<< $line)`" | xxd -p -u -c 10 | @@ -85,8 +105,15 @@ cat $INPUT_FILE | tr '\n' '\f' | fi echo '}},' >> $OUTPUT_FILE echo >> $OUTPUT_FILE - COUNTER=`echo $COUNTER + 1 | bc` + echo $((COUNTER + 1)) > $COUNTER_FILE done +} + +# Process [test.hook] blocks (with hook-cleaner) +process_block "hook" "hook" "0" + +# Process [test.hook.gas] blocks (without hook-cleaner) +process_block "hook\.gas" "hook.gas" "1" echo '}; } } diff --git a/src/test/jtx/hookgas.h b/src/test/jtx/hookgas.h new file mode 100644 index 000000000..4af4b374b --- /dev/null +++ b/src/test/jtx/hookgas.h @@ -0,0 +1,50 @@ +//------------------------------------------------------------------------------ +/* + This file is part of rippled: https://github.com/ripple/rippled + Copyright (c) 2025 XRPL Labs + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#ifndef RIPPLE_TEST_JTX_HOOKGAS_H_INCLUDED +#define RIPPLE_TEST_JTX_HOOKGAS_H_INCLUDED + +#include +#include +#include + +namespace ripple { +namespace test { +namespace jtx { + +/** Set the HookGas on a JTx. */ +class hookgas +{ +private: + std::uint32_t gas_; + +public: + hookgas(std::uint32_t gas) : gas_{gas} + { + } + + void + operator()(Env&, JTx& jt) const; +}; + +} // namespace jtx +} // namespace test +} // namespace ripple + +#endif diff --git a/src/test/jtx/impl/hookgas.cpp b/src/test/jtx/impl/hookgas.cpp new file mode 100644 index 000000000..da9d3643b --- /dev/null +++ b/src/test/jtx/impl/hookgas.cpp @@ -0,0 +1,35 @@ +//------------------------------------------------------------------------------ +/* + This file is part of rippled: https://github.com/ripple/rippled + Copyright (c) 2025 XRPL Labs + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#include +#include + +namespace ripple { +namespace test { +namespace jtx { + +void +hookgas::operator()(Env&, JTx& jt) const +{ + jt[sfHookGas.jsonName] = gas_; +} + +} // namespace jtx +} // namespace test +} // namespace ripple