Files
zeekay b37c13bf34 magnetar, ring, zk: the last hand-written calldata bounds
magnetar forges under a single reverted read, measured: declare 7924 bytes,
put the true final byte in the spare capacity, and the precompile answers
verdict word 1 over 7925 bytes. len=7924 cap=8181, no panic, no error. That
is what a missing bound costs when the input is a window into EVM memory
rather than a copy.

ring does not forge on one reverted read, and the reason is structural rather
than lucky: every length-bearing field is followed by another bound, and the
trailing open field is s[low:], which bounds against len even when the read
before it walked into cap. So the over-read lands as a halt instead. Recorded
as a halt, not a forgery.

magnetar's exact framing survives as End(); deleting only that term accepts a
single trailing byte, which would let one signature ride many calldatas.

zk: plonkVerify reads its nine points and six evaluations through the cursor.
Two floors in verifyPLONK and verifyFflonk survived deletion because the only
thing they protected was the KEYED path — with a key registered, a short proof
must come back malformed rather than merely false, and nothing went down that
path. That distinction now has a test. parseFflonkProof's floor was redundant
against its own reads and is gone.

Removed in ring: a nil check on a slice make() cannot return nil, left over
from the GPU batch path deleted under M-06.
2026-08-28 12:17:00 -07:00

277 lines
57 KiB
Go

// Copyright (C) 2025-2026, Lux Industries, Inc. All rights reserved.
// See the file LICENSE for licensing terms.
package magnetar
import (
"encoding/hex"
"testing"
"github.com/luxfi/crypto/slhdsa"
"github.com/luxfi/geth/common"
"github.com/luxfi/precompile/contract"
"github.com/stretchr/testify/require"
)
// Frozen known-answer vectors for the Magnetar verifier core.
//
// One real FIPS 205 SLH-DSA-SHA2-128s key pair, one 32-byte message, and
// three signatures over that message that differ ONLY in the FIPS 205
// context octet string:
//
// katSigHex ctx = precompileCtx, "lux-evm-precompile-magnetar-v1"
// katSigNoCtxHex ctx = nil, i.e. plain FIPS 205 with no domain separation
// katSigSlhdsaHex ctx = "lux-evm-precompile-slhdsa-v1", slot 0x012203
//
// luxfi/crypto/slhdsa signs through circl's SignDeterministic, so a signature
// is a pure function of (sk, message, ctx). Freezing costs nothing in
// reproducibility and buys everything in strength: the round-trip tests mint a
// fresh key every run, so they still pass if the signer, the wire codec and
// the verifier are all uniformly wrong together. These bytes cannot move.
//
// The two reject vectors carry the cross-slot replay property. 0x012203
// (single-party SLH-DSA) and 0x012207 (Magnetar threshold SLH-DSA) run the
// SAME FIPS 205 verifier over the SAME parameter sets. The context string is
// the only thing keeping a signature minted for one slot out of the other. A
// verifier that dropped the context -- VerifySignature rather than
// VerifySignatureCtx -- would still accept every fresh signature a round-trip
// test minted for itself. It cannot accept these.
//
// Provenance: slhdsa.GenerateKey(crypto/rand, SHA2_128s), then SignCtx three
// times over msg = 00 01 02 .. 1f. Sizes are asserted against the mode table
// in TestKAT_VectorSizes rather than restated here.
const (
katPKHex = "ec882901a80f26acefb6490162f1abcf8edf6639307429821b427eda52a826b4"
katMsgHex = "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f"
katSigHex = "0037ea2c73cf69a0476139796cb9092f053325668c7b540d128c7970f6d9aa0c32ee9576aec345aa08945790bf55edadcc83238c5dbee92814a35aeb043a16bdc908285203d19bed14b645ad79ff0a43236873d6841f702b71adac1d238407ec75b8e6d6ce9ec43979b7e84973e6bf8156b08cd949d24f7c9a8291433911a966e232606723dcd9a424dd43ff09f30ff6c2262841bc243f6aae0b733fd24fcda999cbee84b08bb88481bf515beb9a61a7553036987cff01b9ae03e51111f8642f473c9629b5a348c974b6753e091039f9232bbdd1700fdf27dfaf2d47841c4b8125d252787f6d3663698dc9b6cf0246d063b2e8967320c6d21bfc75406fbf37e7d3fcc52c471e40f6df964892edee29aee4f7bca4ecab192e0478a5490e3d76aa7a3a469af2f374ef3704d6cbfc7382f1aaf9972e047e52d68633c8db040ca2fdd39b70737463abe9931b790e8c5c56f041457d5de7e15f6ad0c614b74ab473bc2b245bd7ce1c34a0d8e0992f4e8ca6723b2d64d603a6888417bdb009766764f4dcb0c833b33d889483f446613d67aa774517040eb025a35ca67334133590c09beb8b2781f3b63969f28b2131f51a3c0ea114425f60897be54d97469e2d28a97b9ba0a3e5121b9531667e717ee96077b3f7b74536eb87689cf254e01716a76b81c2632d7846a09a89b590dda0eff88bd56fdd14ca0695cc8b1e5d7e0011ebaa69b8f18276a62ec9a967171a893a3518d7cef1fb67592ce04b6a78f4bc3391bf258b709c1eaabdef04a29c6fe76967918ed1d728db72a6b7c37c3ca588bca54c0c846cdab3dc41461bd4ed476d35bfcac5f360f77e8dd6eddd2793142bf0918899d828e15124b0cdf2c10aa18b8b6781519c1c5c32c4ea98dcff127cd4297c6ea775011abbae65b9ede159a64049a9f013d44394b742570db476e780bdc9f62e636a3b6f034142d1bf85f36e2620758b144d88e379552fdb6eb80a7a285d2e1705f1faadf36c62a680e3195d3f170e2b624847aa4e053078e84bbe1f99e6a203c20050d3334c6d22d67224a455f09fdc5adf66a858af9a5f9feae34bb3edd0469a5749082554ee94d5561aaa71279905ca2d0e7ad93d1bc1447c6402e4ad6d07dbd3cf6e7de74c3d849233fd98e0420467ed261119ed872affa26c4b48d50221a58fd6271fba896be98021b6ee778fa6e2ea7175a60089a6809e892e8be2f17eabc4759f4f81fa8a6b94d15f5bbccbc54689b90948430858d0c4f17fc889c954febed2d53a3f60c1841dbe31adb842e4b6b027f325d54da6449f054ed1f35970f6ee78fb9c620bfecd01f70b5eabbb3177f39a72bb6589aaf43b563fb9ca663984608f0b584fb6b16666c7893815fdc2805c70c84e1877d72158901d5e569218f3b8bb0c6640731a677122238671a1cb6754a363634db8ac2f8ac45453af2b0c826c348d523043ed5af942edda0bff484074274ad9ee096cbf712ff5891bdf1b2be9726d0007dee45e9603fb1f284da377abee7a2305870c284443a965bf0279419741f5d2f35d04250cbee26b5edaeca9138bbffde073bc87a11b08dd36a80e29c5b2333cb811916f1ab0f3c5c843218be2730c7f6eb9d23d1be5d56f20fd28b3606dc8cffa4e323c503e7ee6cbcc44918e000bf43d00fdcd5b4cd86a1217f8b0f58e7cba5aba8928aedf7880e0d9438928c8893fefb4e41734ffc3adb0db47a4b33ec9481d5e17e8b5afb024345e90dfd9929abc888ee7f71e1a8d27393e27bf8859afba4f8c1313eed3052ecfa429618757158b120b27a3862695e4bc77a4dd86be445f637e90392d8771205c0aa836cbf5652949c61093c111c21fb700339555be54f946ea2f53e5bb74264f6d600b4e9ddb5342f34a81031d794047efb98ed1158216811f439682ae79460bbf2135f155665b11e8bccdcd88685c0e454ebda25033f33d01829137963fe7894c25d6ef31d06be25861a2201c4dc6a26ca246ece8ca04c667d5ba45a127de68cda1c9829b333a39073d1f4eb9e63bb449174b3c1d1c77443aad5237ca714cfa876989c1903b4fb295e15e229440b70560e252252c5934273c82944416239010338ab2f2072f496c4ed6b9f81461899f73b5821606ff9ea213a4a22d47794e0c9fde9d1d2330b1a86584ad4f2bf88363b5f3e157ca490fe256d367ffef8c3ea6a8b3e8438c859325c4c05c19c3a3bd04024aa371f963f1f6904e3d4438e80bbce4ed22ba714b3488d2d5c9316a5bcf1af8d72eefbb294de07a273d623dd1b2df918b64e790b69415a4bea384c09262015594439a644ed0dae233b1a4e6c22f345f2cf3c1154da9a14fb328be1c45f726ea51abb9f8cf504ec49916a39979958e5300c177a75f5288df5ad3c438f4a28e2f0b7ab683ea125f5285ec4f62c18f5f4ed786d83de287ab71bdf7ac67a199d453d8d12ce8b764e879d2f6c11e9e501016619630c3c0a5b05e7987f738bde9d463a46603af0f1f21162ca3a4ead1821a1ba2c96b64e6b3a377b3e003bced6b7ae235453562960de381ec926d3f6f906081ff9fd2dc50a86bb1501fd47721ad00915963073c166e9f003f2a55dcd63c0e36672736b1faf3bc9174957cc449ab5243787d8e77c0ad940f7e76cf6529844ba33fac8d05c1f5ef698aabd540b303997774f03e9b9e7f45819c6c2e655568448e6c3cc5205eb1d29ff7026c15c9a3d5683ccac5e9b727459b434bfb9fb89c10819667803ceb8705a2db3b3f6a26e6b30b5513b3a376b9c2c636fca86c63f85e0839f50bab9d8d9ff5b8d74536a1f29078c8cc9693f5069d8752da08a8e90bfbff7a39d4260b7ed1b46bf14f49de2751e6d90c68467437e8264318872916093c3115b94b037b6862332aa83f037c59ca28cd4acb3e9b5efbf65e489c3310640e63141a1d7fcc2decceaf2cf39f586c2906a84ec935d1ed7137c01f490347753304e065991581cb33204538b0d9722497c3ece8974c24bc0aa518051d0c1cafcd2f90d87e6ea6defb3c38f8bc9264c35b00e315289e198b17a2bb3b4028a063c2c305538a77cb4c2348588ab65a7e74de3ea79bef78f31da494cb8d6c80d4fe1f4ffbf5fea0e86c5cf586a3d0e12ebd8affdce32be3cfaa306db0e759f7ae209dff211a0f42b34b4e02bc5db9d0041ecd277f9176340b952bb91224c492b0d9a74f5c8d8ee6462d528f6d1c7e0ba27158f58df9195b8bea0d3cc07cd240105470f0128439bc69b2d13f31d1a9a6f16e45b5cd58fc7d7b555bfa66cd81e8148eb5001e9a60d2be4ca0696dc4b29af4ff3036a733e43b6b7d4c3fde34712bcc9332d5fcd53c86f43068be3ef70c606e817eb1b52e9541294f03cb5906eec3da52410d22070f44328dc05676a56e0e175f8e3088373b3f5f6dfdbcc233fcb76dbca90e6f84be6407a8bb6eb50096c577a381361d1af5036bb3df21fba674d150a43ed9856c0e540bbc7b2921c0079cc5c8497ab39d23e2ca8804e86683970852eaccdd2261ef1c6d2149d709d26d28eaf4399760e29dff7ae396a8a6614651956b70b3cf4c43c0a013e1492f8ea32180d5bd79d7bf8da1ce735ff2778205fc90a34ab3dc36c70600f5fb08bc5ed27950de9d514bdf5a3d0f2e54109c42400011bfe7b7443ed0383f23648a96346edddea5e4b4686897914420b449fc91996594952250eaa4b1bcfab8be9730801730b490482275797a6984dc8133fad2e4a9dd291ae31836e67b78adcfaa1bbce758f327a28ce51c721ce1b7017e5bcec309c6cc2b51a58d9ca7a1e534d57cede3185566afc8bae9c494a2250dafd4ae23c565f09b10df1b055f63879cb670d9f12a2aec8c6074b6d7c265c7dcd3b7a3d28d6d28456e9e54ce2864e9cf98c9ee330b49103dfe1b272d2f0b8c1c1cc23c512d457eebebcf8ecf561218e9f40b1ba0c2b86ee13cbeaa386f42f1434dc32eb3ccf65bd293c257610d9493f5dea6aa102933816570baaeb372cdee9260200959a0735f0bf60f65268b5058655435190d5a7023300c46af1883cc1ef5fc10e3ad7675ed2def868affcf18d453a89eb467b20da970e6a579343681531acfe39d0d269a205e46a166973559b6177c97b73ab6cd4e33e3f12b04101660afed62a4597189d9b8eadd741a007b96bd349acbac70d7a5c560d240c2c4eb925de7999f29102525b975e7f1aec1a0ec7c79ad44777cfed63736df509de534106dc3d6d963479cece06ff19515eb3d784bc6869d3161bffc82772dc319a089b7b441d7198d09cebe192daf08ceaa6e6a059ea00350e4d8b78750cdb43d7c80147feef7b13b526d958a616585ce4931ccd6d9fd430573739acc38295edda0b6c0182f62ab9de90a9fed1f56797f8c90689abdaf5108c50386560c7873289da1e65162d474115ec05d445ae0fe8fc8ecc10d4631e4c850cf763705817794e8d796d9a8dc5de3c095489637a3091b9c9611be847a9ac83ad2dc1ebc844a7fd9e9b915359f75bf4677b70ac11229f4f0aa2bd8b4bebfbe74405e135cf295bb1e15c3be8fb73ee69e7068cb065ccf7ac6d1e18505f124d1a4e0f7b63f1c01605a949d6fd2e5bccc21762b43e0fe60a6292e752843582a9fc22ab5a1ce8d182d9cb35daa24088e985fb34de2787ac63f38df40dce5770ce005c95a8655c2d99b30adb0f8673787a810f9088984fa780d92efff1b367dbc9056a2411019ad1e7ce293000cffdc827ec8c1a5d69a31794b5fd4548d68d1dc003080648cc64b6736b9c4876a16c4953dea57819a0ef98c6ba8fd74720a296a552f8fc0df8c1deae97eca5a1ff46a7bc21a2b8b3ac4a11f73be8be525af1b6eabadc78ed77702355ce0e418ca778eeae0878dc662e3ad002f8d2408c84965e9daeb501520551f2b408b4c72a1699d88215406561bcb8bdaade00aa6431dbe61d90bc927f5393ad39d4e8aaa8c9448565b97044b60f18ca8a7db7c799596593ec342a4c5771b7ba03647cbee59ba184c8e5ce14f8fd99705811ed5917543e56e480334c48336ccd3dbc4e6702a25e3f2e85eaba0e5518e44597654becf5f20cd7e8ede9b028c853f6d6b27fbc24e77f184d0f8115a0db3c808367bbb2284e2e0a904a67780156703afeb33be05af6959a9b0514059466cf70617d6c852da3b0b70542f7a3ab0665edd2e87753d604d9dd3c6411b01a0651f787c157015f1d3344e7ba389cc0d669ca47776b68d9232bb8d9a29b162b2f533d5557e726d4fb5859571e4d8d748d8dddf3f5dceca239d9a9147b1d89a6841a88379e0e33b3593536d3b6cee5090ef22d739bda82fa72b7da6a539a3eda00a91dbe375b5c6d0d6e8275c6aedaf9fe8697f361c6113ff4f1f8ef72f316b09b9cf643fb9244f47fc7a7033aa1fb7059f3a04ace92f84ec51b581fd914200495f54e45487f2c00f933bce5dbc792cdf28c29c7b035fd63aec5b5b9936cf465853b453934981ff8a69a1903352e6a147683ef3c7b3dbcbd8bbf7dddf6358cc86df9c93c431d2983a3555247e1c34e1cc91c3f89f735d6671ad378998c708c1e30e28ff96f300f053f2732ec1ff5b3db658d2329892fe51acf132b1cd1a78c10f0170101ee8bba3a33736ffd26751e289f6218b2f59f51a97860eaabf9d3e035132cac6c5fe09c2da78265a8dcab1c39ae6245dd08c6d15ec887cd125499df930f55c539b47216c4508dcbd815ad7492cb09b8b31a22d1c4ca96195a81f0a048df961eb624fa7ad3f8c4335f7350714806acc256ce3959030d8869c5c1b11aeefb76d57e6e1ef698770218a65f8b31c306ce9e63a6c41e8e415bc005cd40650e490aa85dbf527cc5baa7b73f1e39bf1f694f49176544e17ddd786af0aeebcd21de6fb149270da5f678e3205c50c8b304a5e8134ab7564caefc1aa2521390a58350ab03546d6015315901d4da592efc0fcbf58ed568d2856a8cc5142f67d60031581ef361c258c4041439f5dd44342fa60ab34cd59981c69dc370f517fdccf99632f0b448c7d763e5e88ac6ac2e5721664db87fddc1fa77c6678f217697ea238d45d2792f383069c77b827194f7d0f7dcbb65b5eefcc521838fef48a44be2929c502a8a7fb26c7bd7e33c62ced855a11811bdfc2f45e6236a10e446a4f5efb704365c098b08b55ffceffacc6d74d2b3127e76820ea4208c2722bbc586ffb8edc6310ba843bc5096ea6b8f7ded27f611cf7e4fae8d31360a1d6fa47392f474b250b112f08b25d0abbbd5e9a36745bdf9d09da62c86c4c6771fd66536b01d16266bbd9d7cc49e8172f20f8350e5398054c72496de49a102dd0487b17ccac45d294af9a5914319c51182374963d95b4fc4baf8fec1e8b32d552a2692adc3605541348b472b0cdcbc843858b541d7fb04a2399491ec8a9b16ab2c5d8d6f13016abc6faa889118ba2998cf67897e04c71383c3438397f72e58778fcd4283da3e9d35fd141cf79573e3c9cd0f5add5ee1ec6bdf8ceb1dabecd08e4d87c6acf9e6e2f5350fadd7cc33ec7a5140af3b87dc482ff9fbe062cc921537fa042b3d1dfd3504c5de7f36d117eeff7850973bcc65db0e1bea5ab03807694458aa672f88132b758bcfe15d49bd2fa097fddce4fc06acf8280a88f77980b232d34eaa9250e854a0c6c6f2da009e909bfe8df003d399445581ced168e418f1f66288b62705899e0fda06f06afbd1cae40201f1c81366437e7106f42209472e5805f6ab49ca4bb2f433d41058aaa7bc039d30e91deb285f268d2c80e60cf3b4851393ff1ea61c47b748dd7e361c510785d0884eadeea15650d2769655dae02f0715a3dfea048cb1d24f94dd93a0f8b1e14adeaa2cfe93e9435c8e8a2af1e110cd4e9a68318dbf5bbfc712b93aa476418633d90db79ea3087861efc0646bb5e0ac0aabc69b579170d591a49b3acec9c5a42769f98cbd589cd8ace8cc8e85f0db8ec0df374c22be9d746807c435437e0e8dfe2530c2ca2bcc5d5529427871cc8b691012ab35f54843de49639cda2799a0b2779145946dd290f0516cfc3fa758b552a928ecd5e05e2ca41da340e56bd70a7cb4a9b386a3f0cb6c24252afa28c0a3f3ed1587c8ff39d4295634b102281a9ee396897366d965ee899d2d3c5b392016ceeda6bd524308aea6b1af31ed73307d53e3cf9f42b5c341324169742d79dfa06fbf388f1de26245bb2b037f313c27152f8a48398a89a518148e2f82ccc426c1be0e291fba61b8bbd4aecb1a52fd45c2a8ad15d05cdb3be3a562531b9e075fb6eb8d14d35e58e7b48d7738704ed9fc381c8a00afa9bc81c0599e6d31920b887040b2d12bae11d2da9b98e734599e049e0de44144d73b9c22cc51c4f75e8931361f123e60c23082eee2626aa4a0e20acff2daa6cb1f4678e3eee7a8e134b5fc3f790c72b433217c6fb1a41129de0da51ea6065e3703edc573f5b68f7b11b2f690f5eeb72ec4d545572d2b2038092b044a64ed14111d701a41179c2fd5af3e2523a9e1e1805cf52742ba9bc07697256cad5f2b3ccd578b50aa3348e4a6682484b066be7658e3a755cbfbe9d4f5162e3a20e15275bfef0c56f4d44bd2fe4b98ab3ba516b779efb7d442dc8b66cae3fb418a57acbfe702606f2e1ec298f6bee44ab3d8ea94d007e4cdb70422b6b824f8898b4d5af30818d2cbd057626536ad38a2fed7dbfd9a55d4804a933bda00e4da4335fb3564235635e962039f04bd812ffaeea6354b52f7917311d32446b25448fdd4ad3193b40cd090e13247cd2a31f2c9df169a57efb0a470f62e081ed570004f2259d9b07c4e6b4cbc5745afca35a76baf0ca13feb01b2f02566482df6c4419b8ddc21cb8f25e759f19b0f33223964c59a99f190a060931ba7d5d17ec6e70ef3cf1f29bfe3e56bdac4e49414f5a393e7a047ed64e7bd497a4cf95d43d23430f9723fd3c91b61e8401b147fbe4f935c5fb833fa2fc9b90f7973b118676108ace4c586adc96508d735021f67d91097df8cdad00df954880b5c9611eaab0361bef41bf7e838fe62a0eda95e86ff884894bd18dd4ba46ea356ba7649945c81f74e543e293470e644f8b5ad7b8206927841449f2f72ae3e73dc61a7ed79d8cd21482da475b6cb8b4f5a2cf441fe43da7772f4acd2b9680e33c1d547aa5eb1d14a5e65a58f4c74aefdba56ce39c038b8753019a70b120b64e85cabbcd6b76f4341a32e3b20f90795d841dc94cb48529be142012997175509dcc356a8264e22c77794fd78733a76275eb8a3ab9f5a38a8a3c14f227e280279293c2be6028ad8a39a85f6d27beda50a20ce1b9b09a8b2de0a8587cfa1d19f07890b5a7630b7f3145bd94f55153d143a507e7d64849da8a1de385477952501f95cf0c5079b80d1e87f2f0969e0ae05437b022c32b422ed517564fa749157cf249ab0bccbf42ece48e02984624f903a7c407e84c1d422ad963f8e94f24130249764cc9da360dc7372e93cdf0d491030ae4ea30522da2cab69408d5ae8054c5d652b0f701a11183502b5819d306090e6edaba89c6177d0650ef648e26a76217d9d1bafd55c47251e3800fd8b65732e3aa567b162cbb75ed4acc133890784e936e273037b83106d8d38cc593de58db9931a70fd169c54469d6e5070064a7f48e19ce0d68633445b130ad3cba277adf292ee1931ac1dc43996dc375866c32525f091bdc044f0b4676b5a58f601ddd0b2a19f75e1c87e49b63adeb7088f28cd98a65d61e9c9be199d7463c38b452ffce4fdf9406cb4777ead27282c2b61dadbb3e5d622b808d00fc2423cc415163877d0bf948ce93ebd19f39024374e8b503cade2d8cac27d51b5cb4e4fb94642c7825983d600ffcfdbe4608d32228c1fcbc7ef58920b91f40ad47804f17d815fd771f7ffc5c42d94fb499dfb9cd30c20d35b0be6ce1a9ecfb0c82c791f9bed82dd404326867c3301353371d0af698bbbc2226f1339038d5ed3a2a2bd76d7a3d9b31fdbfb5ca9d6a723ef3d9c19697b3fd5f96e31607522eba978c625bc31877901a7e96b4e2d8b89b0b66127f7de9010bce8c25d1b7905ad0b769082082afd69830114361c5ab2a931b4eee3bb49758f8a635b79adc5bdb90c047f6e5bd5abc92941ab7ef3c8c24003297aafe8f1ba1729d5fdef32fefa6e871199bd87a37228d25a9c716da3f662910add294e2fa4bd008d71a872b781a331d0c18da5c9c4fb977151d36dcd19578d25784cd02263b044650af5bcc97e1cd056a6408909bf1566f6c3b265224fb34387d8b4ea71426d7c6311fc730a97cee440e4008643c8436c0047a61d8f96e98a01daaafd13b289f389e8b6d31dc15a75becfb7b6ea9c2d9ae2c4321a6d5457c0e0ba2213c60ea34d5465a25f0a873aec6dbf3524b450596a1fa1278a33d727412a956cea746dbb0eaf8a6a3a0f967588c8e7588cea1c254ebb60093ad0a1e6344e8524dd63a4433ca346edba83f694d6bcbf6746db88375f9e5d318553cb497d15cf273e880839bc5355c11e69bf0238599adc51c69676457c86d6ef93780c1d66ebf5809d98d8c8c63e1ed75a406e1c5e64508a24054f12dd486da46549930922a53529e6249ec090979dd5d4479d8c62b6728529cf64a5888d4007d954df4f9352963a2e7bf263f61d1e7bc59183ca60c266fe3c08ce0ac04ec2ca55430eb721e7bae607e8e3152b7b513d18e8be65a683ce6c1cf350563fb3786e909335682101c9d2892bafd43ceb71758ff8bcb78246d5b2b580f23a69031b8df2b740d7161d5a2cd8221b85407ac53028f822dc91fffeda618a8637a59b0f216b444b2b78d5e2de12269530873a8a1b2ba11caf4b5b85a6b98bca49657957a73aa18a1d4774eb769d9c04a2c86abcd94dc3d35210f8ca74399c0aaa26a57ff893d07aea1228261264988675485aa0692c21c1722516c3323d6e2a7519b76de72c81917eb78dd2640eb2b9e730b74a8bda647fe8f534236633ca39331b677f0bd47ee24a5e8daad2ce2ffbae24e58790a010e498a7a47d6619a06816ede6eba0c4108d1c3929d07107d62af6f195a256a436be11c9459f34c967646e67c3707f58a844df28fb992e800b0fb06fdd79e54fd62b024e6d242f2a6b56dc362a929e10896bff4aa716899df05f2ed105e254dad85d3eeb4689a8cc83bde6c3fb19529bc4b061f2750118c83013031d44478f09744033249afdfbdf597924f09b3e89c082ae8bac082e028aa5b5ad13ae62bd590d2bd330f5c7eede699b41cb90617b32caada6337acea4aa23cd93e2ee9a94ab1df56eb69d3e74e28f5b17da5130a25f0b20f1e36e7c297ea542d44306501f011bf7df6abdf1446898e3d97289f3fa903fbd26b22662d32f4bde6e08e8dcba65711ae796d392cf9cfbef2cc5c79b1b1dd30e776ce730b820de0ada8eeb88f1d66440e7afe7680bd5278e14ef7d84a6bedcea636f70d22a71d6eac0ce969ba7d9ceae9dd4fd8ca396c5bc8cc5b40f2ee5e401b1ffca374bb2cf5e783905a865fabe24d8a7433646da845b348325d89964e13402c4466a9edfee58ab25088cf865f9437b05fadbfb8e080ed23a65e29ba85cb6c4c812a0ba11220cec8172aaf5eee52a75b3aa54ae8915a5071f768590252e0bd01a41175dfc8ae0413b13a28f171756d931ed95ddebb072a1f4c83cf930182a1ec5be58ef9051f4057cc84282960ac6c44150942fc3de679172f1772232a6670bc83e5703c0501528f4d6081c225148a47662994c67885f981dcde508087c1c58464b1ce3c66d93c80e78a0b5eb3dad419443d690613468b69612e4f4fec2398065b079eed5947f8102301b4aa0306bc81b20aaf311862cec2304e7c52690670afda2285598635df6051351223f37356df64cd89355440106e51fcc95d3eea681519c09abd393c2c7b4e71276f56dbca0ee66b61538d9fcc02cbc085a0706cad6b178c5be1f5b475f63f20bbe988e0cf722749683e49fa8dd6f53d03017d58b788aa07e3bae4940653336dc5e4b0fc11d69a6c5d310f2f33f85a036ab9b390416474930039597f85aa1a71c57f51e46b421956201c917645c89031ac178767e60288f6733b41f5f5e5e4b867432532f980d0c1be4bce50709366ac49a601dbf0c923c899c333899c11379c9c3ad9470a065f0101ff"
katSigNoCtxHex = "d7148c829f46c411264fb06e5d93e5640a153976b9e066e990399894f6d3541cb340aac74bd8923bda0d0dd8b74cffcc527e303d456be4d7b1858257daa65c460912f58a90a183e10c9ddb6591a2481392c996f586388cdaeac09bbfb5c9d21770b600b3d421d6fa5cc6331b4f949a6fe968e0c320c8012ed409d4f2adcfefdaaa238e2ac40f100920744d1703ad19220a9671f801dfd107d12737245aabdb516516c3b52f17fd4b070680651b5a912f62a29c1f4ffb5374de015c4271a91f9fa7b260d464c375837cd56e6c09d643246b4f9671af26f99b9be8edd731538375c4ffb70e585d473bf2a52d8398f8444743eead8ecc05bc2005a48f85813424f34fc9332523a3f757a60bf999a1d47aefec1f8565e999ac9433f13b47f1cf3fc8f65253bb00a753cbfde3afd79c6aa05d3452ca4884e2e13874d50ce26a2e0de2610e7c4ad7c7686a9c3cc97a3a53624a45f676d22a830192482c368ea90d4503b4d405fa38d8d7c186c5051fc041704dbf88544abcaf62346f2e4a5010118cf63e188d9c49b4160e7ab0126039a91ebd14d2b9b4bc15dd5d0c0c4cc2e61440755da5eb477de0c948d140b2e0141ab4c8c52ced7251be90698f6e904d285c9d6933b50f2332bffe41b70c3a98db295549d9b917da795ce6b5e74c3f9124bd7c7385599e143ac3c9cfb07d5cf158da0c346f4a232046f27c03b2889e15bec2bfea36a90068372ae13342caf0bfb83d3b22d3bd184a2709e667630f5749d65eaa0536a7f674fad67d06687f7810a907e5ef9f074be72099f7ff52c9756a75baa5401f6ffb5cf4029ffe0f2c1c3bf6641d7cac447c1cb7abeb3a19c572f67cd13e3999fbebe5cdc28e9a3b6e7822e72145b9a3f713af7e6b64a801fafb6871396ffefdca24090aef58576d14dc535b9fd2f1ec798230eb0df1486835a30855973e88d6192c2c4394000e287ebaf5d23cabe5035c80b5bd8841fa72fef9a9b2282151c965fee7211429316accc34e0a89c38d9783ab74bb3888c9e1d0404e42763add685b0fc859420d73bf497eb31960eba1619afbee16c7a46cf718a61df39b43dc60b25f8f84301fcee8b6ed97ad6a3a3fe5a78ecdeb4da013b6a7d390f22766ffc64490ef38b9f60ac16e6960d462438b2bae99dc3126e01954bcd3c8af6fe3248e1c06655703cef788f10435749bc5fa7d0fbbfa35ecd0de25824f907529c0fd3b6c38715fa9b1786b9b3d8de91955be696019d9963262a3d5a5c694076605d86400a969a6fd3fcacfc500cece7c9f343e938d35bb9daacfb3061441340434d4c1f24f1447d12d9bb1cb26597e089b266a53ae300461e8cd8537a4bf6e5d5ea3a82ed0450287f172550161feff8165c0d65adad3f5bc1a7e3fc87323ae4e251b5eae80a64b86fef2872e79bfb636b89311c95028f3c0b9d757bc130754837864549a4c70fa5dfc464f11657ef93d93f454781ade3fdffd8e68065cd2df46e7cd4786651d4b1e853e63909d1cd794b1ecf3e1c364f7580cfbef3b2759cb02bf51f952fd321dffba6fb0cac6ef49a6e4d2fea63a259ed36703cb1f1304d3103065e74d9eecf3c011e35c74ce0eec8519b8671f0e43c0f770f54a01ce74ea96366fddec20009fd98ffc893805c196f1230882c4a42fc19440c18985a7472d14f7e721105522a51b8dc19840f6a6a4efdae3855dc64c94ab2c9c42d2f6b73c677dfa88b3f85af94ff7f7b838e26da883ffcde24a8a52a634e75ac1509fd7ec47b8a24726a5de4e0039beeb035f8cc93c11e0a871881fac536c8003727ef11f9fcf11a08a2390e14094cd3579c64e2c354ad165dd12235f17fc709350c343506b9a960bf2f8791246ec2fc3726ff29937baee5a04df0513d6941e6a884f78aadaad9e45dac4b8313cc85e58f7d8ba50c7ea15173b5289f635608999ffb8ba93d2a751c5010266c960d34a38faa0bb946ab0d66a9544e1b925f8bb47879400db5b0dadfdf6c0ea258f2a4953a4e4f91411df78d9e1b59bac6dc8c84e8f8f9c2916fb58cad6c78ea44509c2f6545811279a855d50a0482a941deb6944fe13eabfbdaf8b04342090c1fe8409d980ebd72f90e9752916f038d2fb6a14208e670e2e6104508403381cfaaa53e6ff16f092f17d61a324dda5ff25f1774ba2d0eaa17853bae2b3c93a183a8baf55b9e21e8f9ca33b7d17b09dbc00ba7f482ba489371710251197065483e93c1e9139306cbdc58434eb92b08de48e756f1fa47a0b9b38c7ddf57a2ee0c5d2ccc0922797a67df9cd131be4eadfe340567867945bb707123630505f58d52c4ff52aedcb3aa8b69c6bd85fa23142a25db6a0afc333f98e2e7ebb268da4958e7d57a23e467cf57e72eb0e4feac1979e3321004664f2ba59952f597b3f660e9f1bfc58df928940fa04b2ec605fb95b83717758165571fa7bfcc0c721275deafbd3439a7c46c667aa1d86f5f54682639bab41a440260a0480537e205b5da6068fa69d6235e72b6f105cf7fe845bedfae318aff18c485fd80835ed16411d939c98cf799303c192448f4147b0890aba588f9c391ce1dbdb3cf6035f7d5e73e62912902eb5911e0f4e59c76f5aa84bfcbede45d20fc6930181cc20c42cd214615cf0ace62f61213d6bc81d75067bba5379bb7dec19d9d935b1aefaebfa67cc090510adc35686b1af341c3d2749605272409d2b83fd2c5b0cf87c837c98316d590a49b9418a5082a31f92b930c3e0667ed97b4977389d4f9f822b1327b85559eb20accff33f0a66339c3cf1a7180258f74229538400a838439029c5790e2c53a40e84364ee1c7cc0863e499e3ba918c99bb5d633490f3935d36c1c5a83644a596faf532bac1e77ea0426d443c6d32db6e420c292eaa8623d1a9603b6f390d134c92c2c41237cc01562434567e88217a3cc38201a6e4a29aa9cd41f3bb21dc127e0fdf8e651661c27f0250854249fd05673032cf64486141b83d687085b67ec86aceafafc78ed1d4b97f4ff2cb05f15e4e367a5a4a73c445ebd4255311dacb28a7f3c347d2d7a6241d12c5c916f61a0615d6ca45c1be5b4b6bb779dd3a989ac05fd112f2880366ee44c2ab8d2aa48618af203f412b89f026cd9b6c57fe9be9f54ad9b8a219168af5f33e2f5bcc5604b897c7e22ac1f59cc2e0a1b957ca3b2c13317fa61ab76c480bdeb97fe5d007b881d7618053f72977690897dee37f7e91902cf37f0ee2f98327abf22b14098040a1f48c7d8ea8081aff1117c6f3b0405ca1cefa54f7bf63b27745adb5701192fcb33b4c3acf72ef14bae640368d52b2afe7d7018941cec5b1366b12d193fbeb3ae30c7cbb6073350aaf14e2920bebbdc1bcc5e6c674ad237965048ad41ddeef0a5f3ea6aa29711ac7e6b41dd20c94673cbd4f7671706c6c635d3f915625229841afbd8f38d8c9160f78dbff2824ad5ff2ac841c4932e0397b8f3b0398be9837ce8c09c3c82e6ea88b7fd2d6c107796ce9dada50987d0c6117c8af4721de35fd12c24f239f2fa20b0b57eb1a92f3273e58714afe00f13005df61c44f238a93796de3dba06822a201aa4f514779f43dba2af2b588d070f22a79b0c83609fae0c5f8a2182a0775d9a99e79fe48492d92aa7cc043a3be8b05db31a46994da40dc88941ad8f53b3688bf958f8a7f07e3aa1238251b5e024e11036da500ca50d2123d8d6d147d03efe9c04d9c96801217a8d90d87ab376e5e428ed5ed8682d9b086485f59d78c626b1f27121f4a70dc8635fceb495751aa23ac38167f9e121962eb2ea4b162917136e6979b0e29d72ab817bc3485b15bcc444c04d80a8a3357d3fc563c1bf8b7c244775de1cea13d84a6c11fe336fd6b2f1407f5e69f8205b51c6d96fc350967b20647e514855a950c83083e1a0c276a42e09379bc9ce63174be04881a7f5c35f7663d64be45467fbf310753db4fe2466a41632f812623f8c48a930cfc010b9aa3d76e143f0c7ad4a7214406462006d266886453e33e00424f6ee29ba36de74186ba14fec04779d3a2fbdd105cba3b77b0a0aa7c71fc6d6ef50a6ad1f26464e7078f74fcd10ca8cea515d6db7169492323ce030bfda8760e8319ad128af614bfd2e5b04525352c1eda26be33339f44f2e5dbb0baa586b32fb1a7783250221483b30c8f1f6de8149fb3cac1f584dd82b306dc5f91361a38996e7b9bc4ce44fa92068ba3618b509ced82555dfc5814fc3e346cd8ca8feb3f35905ade48e5e075fede26317b7568ee69cba39abb7b76d88d26d702dc392a873cc75e8a09ac4b55485e6546967a1cfb0dcdef27854c1a9373bb214ca43422a46773f39caa13f93c9112b07769b558eeda599479bb9fee0b6310d415b335a48fffb92e6c35945494060334ab8470b3a025a10da7006a1da01df37578d75f559fa8f0b53ad707f204873f1c38c2f7b8a8f3ee0e328c2acddfb8c018b4960a8291874b1df58ea8a627641fb21c08dfc86d2134a52d361e4df5f2432c0a7b8a3eaad4be24c71611b6159fa270de4d5d42ea1e02a7fce6b9f8407e3433b57febcd132f47b89a337e85da73c4d1ef82611b59c4e53b443f72072e6dcf286f4ac029b17e7ed94e3d2851478f668af576861f5d6d626016f7e370e1ebc0683fa7be6cf8cb42c1fbad8869c659e71d56ce7b782fa0ce3f04bfe1278173e765c29e2d18a879aa777eb8e90184543aa5894eeb0953cb85f6f5af609f80e999ecda99e53b94a1cd4710c06b6ac6b6dd4a9e6cba95d487b463d0d00c503a87818e479452ee64decabcbbcd6fb237450d23ada2a1b1aecc4d3d414888433d658c1e8cbe875be5ff287266be7940e5d125faa01977a3fe42d8bf880d941878f5a996c73ece65059191530dce3aa0fa9e238cfc8a0854ace1ddb91c8af43fc68dc7eb80f7855452bc93f1a43a154448823751b82248f2a0e04130201c81ab46cb757e8f0dbf460075c7c3ea1eb3257cc0dcbed6d291b77cda03184a6bbb871f840997caf28d2367c4233c69fad679a83324b00ff937c0bd8eb089e73779331cd563e566c3acfdc4828cf67cc755ba37aae4b42437f9703ddb08be8ae16ba50aced886f947353f97403ec23d15c34e3cbd6326c43e76cc061e427a8d1840e7731d7ede49829fdc106bec6fb55f69ee860cd068d6ed75020a447af88859420177f3ba85acc7df49171ba7f66cd70ab84d5daba82adf559966920a58976489056695a045894044c11ae5c8b121e1b41e634ebab228b1c5df5aa56450ef090d2008444d0623c4014645751a939ec4b158a85d3600a6506574aff378339608bb2a7f178576294beb4eb46eabe0bb4897027d941322817898a07118dc155894a45bc29e4714594a8bca702203d3d26c567a656fae9ca43fc765b1d6561a66f4872af62c24d3daf15c6c3e05b48581a81ac55626c613e50aaf2b3378cfdc202c79b548356cb872840bb57b232bd608e7e1e7a7dc858e6eab5010987e19d44a9a2c0108b77ea46d80613071541dc33550f2fc94a84303578ebdff0df6fa9a36ee0b476adceb30380b4957ea0c7405d9cfbad89b6ea89cb22fcefc5028d502665267b2b225044bab6118302a461854d0f3a2dd99bd77f90fecba60dab3f16c44d2fb03a6b92e2d2406a5fb3db0d5e22a6adb2dac7521c434eeaf0f71d6f84a2bc5ee2e9ce551972a668a7af693c5c99fe56a00315e24ef4f9b76038e9a9fe1affe6186c9f56d04e6ccf16527f2eb546938f865f2d910178486dc6241126adfb11f17fbb4c92285d9d8c9fe12a0362931dc12bc643926598f833399eca28285f5a09ef538d0cbc2e9b4fda094003e6ccab0d0e7e45116ef6accdcc959d00f5ac95d0343807b78ba168edbb38d43b0200f129d29a62248a8cad50fc71a790a194da7d545cb6c147aaabd59b2647c7e9cf376426a4172aec3dea8549d908305020aa607f4392f3b2db325571f29664bf9fc47e550e57ee04f51da6e3caa881465d7db226c64e239e5c86d440547c50bf4b75c52e75c3f793cc4e3e8ed29747045824c9e01828616ef50d486c06c87370e5fac1d36a2d95e30787777550be0b4fae0526eeeab5c234d9bc363e087e5ef19707f0ff0df55272d2e54475b74b4e3917535157f7419ca0a74e5a496111f28d457354408728c732c3f492aa336c53fd4e38e40a9b632f004fd5e5b0008f5d780223acfcd066fb9b463e7814333a1e882d5a2aaa20c5064bbae4c93b084d5fee5160407e546f85c1ae8da67d96d91fe57f7b208cfe4b53bcff6effe8c382901703bf42cce2a50773232b66657b33d1205757fad5dd0a7474971f0946383e29b78445d99cff45c1f49dbc6252e791d75c85b805fad2b996ad713c045e1eaa40e1caa9ba105982624e54254502e1aed7ef65c2c8104f742487899eabf9b20613ebe424e2586c12c5165081a2428d6f6516035f9fcea26b6feac71e729e3cad6ffc3f6ed242d019ad6f80f80e6eb2baa50b2029ad8d7a6661bf44133037fd1177aa20d0f362ddb5b6ec0c7c6790e33b93eb747ae05921a940f0fa99cf6e8e99a29dd65f02ca6dfb35fa49ac960924b532b6fe29cf1e2f54b87c2c3c02a0edfa78e15a7ae04c75289dc986a169e7c832bf183e53101c31fd9d1fdc91fa855b4c55492f6cc7f29811edb1f1b6c76bed0168afd43ef755a38ddc1fa1ae621e1fa268ab13734bf404302dd1ba778305b8640449d0ca90050ab7082da3ba3cf3f5504eecbb86c1aab4afd89ce300803007941afec9b26490efcdf6132173d533ea48baef1ef2486e064793c690ee2602ef3267d223203c94249cb2738f64335867e2a427acfe8d7c29fe9776a07791f5b1334e8f67700f5798eb6a4c89acfcbf49c846ae2520f005520710e6f47e65df80ba6e6eeadd038ae7c9aa820a062a22c21a25e20fb2b6118fa40eaa3ff9c7a37e8f8f25de4acc65ba144c351f8ed96ac30b42414d05ed05c32d134d0b1a564bdba1652ac5d5e555259293093a925933de73e6f5eec42d482202738fe39e7475a9c4e59f75e38a0d9459fadd59cf6a9ec3fd9d952b05a80149a3cdccd414a21d5c22a09be8f9ef8f1849a5ef749fe4bc3aedd9fe1a42cc0a15dc13ec2915ac11508867232b65ebe6db50d7062b7bc2249ee7e05903a03031894820228a1154aecb33d5c031827ecef363533b2ab36cce7bd96f3da03ea898b74097116c6a50562cb57a4cf5108f6d18831bde2a51015cb30daaf948b59a0a938f55d802d0d1eafda773c81b6858fd87b1d0c5a7bb1289703290ff060bc585bdf81e7c05a891e65baf052036bc5619e331812d30fe072d82aa1a10916e64ebec39b422ae22ab21b799c10d241d3cc491fc898ec6762691934f61540e584b265b0a3b0f7170c7d3b57b43fd59a24aa032ec649665033a70c136d69ba9423711d5f979f2eb63d9d37279a47a3ec65459b14c39bd994efd2a676d460ae3c6d2f2690f23be0fc7fea5331d078507890686f7fc6ffca58ea689242d757e6492a6c99337e03bed0de2cbb749481beba8b647feadcbf38f4028f136cb535d1d1967f0d2df3127168e9f2364d4ac33c383e4cee64386240ce76053e6076129ee7e659971d58b05c5208bbd7f122dbedecb54ea5c0c56b6551ea36908e9429cc5a25c3da971a76eda969540395e462c592be1ef21a96f6887eb7963e7d98a80207f0fc0f0ba2ce965b8d91bb483764368a2e42d8b5e85b513296bacf11421f864e9204012c1af43d82466616aa087f6345dfecb1714bc8419bda9177e7a8cb3ff39e1899651da642d9a1b7e1e2ec3a79bbfa55f664344adf30efcbe4cb52ffff67483da2743185568eaed2c35f33438ec7c56cdbcf98591b83d55915feca29d60eff4e5dd6b9b675e10c879d74cce411bcb8af6899b951b95d2e9b01f3046732df308f72ddd46f0eb7867a7202a350dd5e9a267faf6b954e1bb007adea794f4cac6b66944cc5c74aa57cb2f2eca967a47cb4c8ef37e88f09a93974c7a7332f19277e22fd9ce5a259e4fd19294e13a47b5c4938456530f76fda7e8383cc85a56af2930aa86a2e1d24c98d4a813a04ccd2184fd75a20fa6b9af4f56781cc8b4b17b1c3f34bcdf5f6b60c6392aecc0cd211ea822a88f9c7c2eedb24efcda15b94178ead4baf386e70069b7629b4c2238ac635217e144d5e99996166db3b9611d8f04f04dc2f600e6c8497e221c464107d704551ad8972b40ebf6493bd7ca31ab7c6622a42877178800a07d0901981d741254aa857ebf9d61d32a253f6fbf76cd124e0aba13d97bd441b5f4cd0ff7872049ac40e75c92ef2c3b0579ebf450c3accdc8d8f7c9da3336da9024ad8eb5632f2fceb48996e0a4b29bed23179364bef51cfa2e85657bdfbd573a867b85112c006e4a0c8583502567c42ff7dc4952b37598f49b985eb4305827cce5352c0ec0a1610e70042fbd46504cba05e5b307d202891bf7c9768ffc23b669929368512652d1ef9995f962ea328e8960b0dd6357bbdadaa38ec70f51ee9c4508c4402ab41a1df9c23861e4da64e33a9a08871ec9920670be8769cfb9f5cc7f25a4df04d68cb6baeed35d4961b710f381423fcfab0373ee633f03c7061ef7389b406f3c878227e7156ac464b430cc692770821a10c750c5fdf2066286e54af29a9e66d78f2e4564b2c7102e5c50821377db1e5af3a305ca6bd14042efaea0f1b1d111357d552917c9f2ee1743bba62b360dfea23c29d9631048b2ba6d3147ffc135f8fd9dd3cad3f2c1608da1bdb30465d8c5844aeec1bcd17bf36c1cdcb0a3092f1be9436c98910ee074ff22aad6fd30d889d7cf07dfe3f51dc839fd7c234def8ca083d45ab56ea1f627e5b0eb0715fa4322a07691fdb5ef7c9ded7bf584d88986e9abce82b8e0d6627a2c149599d0feb6f08ba7408f2a6eb946a8da92997b0f831fdcd4f38eb39147e9fa03879c1b5a4863815c69329f2d623dcc28a1fe9a7dae634fc53874c5a24fb2f960e124addf397831af0594ebc7821e8868ec5b8c026f6633a9d4ecbc4632350f40d58c53da47d93958e1cf117d874b1f23cf7f6e52f05543263f63361988ff4aad6e4e3d457f1ef43d9e7efd08a9f0466c27315e651a9a980e4905349cc6ed8bdc0ecd8c0c9f1904a1f24c157e8bae753302ea18ac5d531af63d92e95383e00583c78599a564d18814dfea629da05438bdde53d32d6f763f10b2d6c2e75eedac199ef7132f79fd4d5df71f6ee1374433a0ef6a4edbee2ffeb1515806bcb998c2827654f35e8341681d7c5732267b7134694ac3014da11433932c6b9e0a794614b86ea30c642b722f99950356e95b8e4694577ba6d6dd69369b6f1b49edda60e184c19bc3d6afa700a3df8e3f8780991208d7895589cbc67da4053453af04968f6af5279d74e205ff3dba2ea0745abb3bd62058a62eb44e8fff123565358eb5604ac3a583fe22ce5f06b72bcd4b4e1fd186478f3e70054f4b8015403e886ff9d5125fb4a3c4d8f1a1d95fda78e650d2809db65c204c0bf0e9744d21e122953980c4eff2208c527e41918c795165a000d632718dee3768047d47d1a3b7daa9471bfee5e5b7f0b54ffec1adeeddca36d041c9ffbbb54b97c3e94a986762b2f3cb2aa2a206822ab4e8e9b364b0844009abeb1db3640a828961d47fef913ee8a70e507b503716cde031c619e06a7469be01d77d2359d5ab5cb8a6ad395b6f3d01f351ee6e46847543da0a74feed423be8c4dee7d1373f5cd69c9b751c88160c6589332e3bf62301610e2814113139b0b99ac7f63581190e771b2a37cfa11b64ac63fb322ad49fded15e8a872aa520bfc4160ae8e407a0949cc33c03a9fafc4223116260a5ce3ab6a24fd6f84212b3ec05a875c3a0d0886d795e4d0b05c6e157de1eeac454f608a49ce0e2abc03fd413116dcaa7c6716258a8221431dbfaf125577d8bb4bef06d72ad009ab097346b8f04b90b2c7dfc06c9e9f01781dfa7afbb180311a20aabead795df8cfc5758e47b3a5defefd8f9b6c69e4791ccf756e65767cd059029ce41301a0b76be8e95a0ff42b3ee9554cdd2f8f180767bcd0074d2a1d521fbc4d5a6a346a28e85ede4c0c8ac5287ebe9d5e0b6ec3e7205075d5ae700b0ecd5648a09ad99866a104a90f3e91aafb7165c1fe1dad3bbda17cab589f8200a9c61bfd5fe83e59fa3fce505c95adb1b8fb89408cb0711312b87bb70926d51a09a2efb7f7d5f4cfa800ddf6d4653b9948c3256a3e4d11d16e245adae24de52d46a9e9f3b3e2bbd0caa2aa581a12f4578590ce4599f61d45b20e98a707b6d0a6ce74e327b89e3baa458b90aaeec97f48acbc0ef9e3793fcf1bf8285c44cb45ee129556a3d7e2a20a5f69c6989e461aa502a6b77033351dc607ba95013eef1ade810c02beb649759a909e51c49f63d7c6ecb8714ba4e693f80c7d6fa6d60b3da17d1da7cb3adb5d8bdd2930f76ece9071905558f6a903e8a5fc5320ca46decbac623a2b619244a61464fcaf449f1217ca855afa8612ed613dfbc7f0ef073154fb5943ca4d356d96b84d558612cefd7f907cfc0eec97b66c76673193ca8bba5936e7216ae3615e1236d536b5ff66cdad7bd8274aead72a70595a4ac0f5244457d0da65904ac74b01ce5a0eff9b032cc2c064fdea518799f1c482f65641cf42e3573a1ae92d829542d191ca5a4e0e212b1d8f74cf30df7fe7ec700eb614a1e8c48644e16502a107142f90e16a2bb9e7153b34c6b239d3f8380b793c48ad3b5cc73cba0024b76da2bc2d592554ffd098a01d389a0d688d8ede64b06cf20da7db1bc7f8f975bc52ca2685d70dc17e43d4e11bbf4c61edbc8b2bc7a7c7572afd3e1218a5f0ace9dc5bd5b81d80f202269f56f397100e6cf116dbde75df75aa4304a5cee4db804a98878c8f1b6a7eaab1577e23983f2418f7ba2a56122eab57ac98bd038b5d97aada3dbe951a5dde6906b4c4af60f4b2db207698b6e1a2f9de669ade79296d2f186e4ae8ef5af115c733c58b1f01b34910de9322f22cd848d2b9ed4c0e04b237f9f89d08f6996c03db07eb415e21248d08ec2a899d479b9ffc5a0efc7621eba63a75ac3425f96088046e368938e089bc761e8357f0f1b6a5a75333a797a355110fb0bea14208371e00867789b7"
katSigSlhdsaHex = "5cf2b13ef43c7ad09c739b75c45b1f67e0269b3be33818164dbca5fb83745f11ec6922d58ed6d15042797497e39ad58906436d4d78a328b5548752f76780a0799dccc47d44b54a4b3f36da70eb3c585593d287e4e5977615504e4fcbae46fff52602fa90af5d21991e5cb3d2ecebfe62eeb63558e708669919c528a5443fd22c97410d1c865e4ed1ac58f7769934668d9115494e631966f016a9377ca5b88800f5c381741a2cfb67e83bd42d99733c63df102796869d0d52edbaef145653cc629ba1df232a8e5a46afb3575955af3841501c5e6b60ca3b9af0401d3a9f76d8a3aff52772ca27b49030894004a1f05924947db80ff0a800be67fbdc5b82ce3f149bfe50810080c2804ac3e5bdb6840541439788ad9aaa10a7c2edb46e03af2f1738b438710beec1ca01b8dbc83b0050d9f4e80abfd36d9e7c07f29f8075f03f8d29a5f3a98aab167bc9ad3562472acd3d5d10ccd8be8c8ea370c441035dfa83a45df795c3c2be2b1677d1a54e0ed4963b9efc80cbd8926f5324f0bf6b03a2be4aeca6dfd5c774f298653236467537663185bd1b64cd23ba2349182920d9f765b6135157bf2419aaf5b26ddfb50e3317e17fc6155aa5f7867ebf5a821a7a0c430a63925d9063d87aa7ff3074af2ac6664376200652160f61c201ac05133ab26eab58e5d68f6b4f5c617d7a2d11e551b2409a55d2fb39035498ef9a622d550d32cd798009b17a9ddf2cd4ef0eb150a6f418a549d9bb14fbcf6427c090393d1bedf2d878ca8def6c197c4e6e24baf41a61854747a7d6831fa6c6e2c3941126f53d6807a4589a85bf86bc1816e55298e8470c1e4c0a584694af46edae50c0fb209004522b034e9d53a8d545040a8348c7a282e0f364ef37f5e91c17b5227ea585dc23c71105a3fc1a493fb5bcd71edeccfa5cefcdbd02cdd5d2579a1891db15bff19680fb3fd13b2930f4e26086263be488036596d63f2c66fea6c180ce62b9eb8a6e533e500c33e7bb7ef52cfa0fc81f8edaa8e5e0686400c9197df68d773607b3ed744f164cc56aa920fd12e0c9e574819ebf914f1204b5223bc02a470d0b24f4590ae7aa3f412529876c8b7589325adb8c8d641333b8d81890ccff592230349e5129739f7ee03a9cedead382b4d02b4ab96097b343e87a3b8041319b7a621c566e6aead678b6897db5aaaa891b8f42e710f275702b41327758e4c2db4e867822ee738f2c950ecf074eeca7ef580caa23a9e5a3f916889b9d5e5253eb3c5d77b3a854b1209239d72b219c905db3101afb83ab8eb76d8f902388d4ed81ad96e8f89825f9ed6c11fb1326b14d12efd1420c23f9eb6c2941fc6779b5bd182c7aab921b90ef597e9165f0100e69d35f45fc1120f6c45749a8568a6fde5b04d5fd0fab871f911a4d758098a1998dd09e86c0bc71dd4ccb2520f3291c93f9e40e1e5813c12f6169691ce1cd42b8b5bd2e3e8ae078a2fd0c40a618de52a2c7d2f1efb1ad77eae27707f7d790a3b75950472a7bdbc744d1d35002451257230b514b230c25ce9e945d60ec925401c67f73a689f8db2cbb9576b069816c3b514eafc7a482ebd88136e0b7073aacfc4623f4a62459ccbaa4f86180eac0c59a35ce2ee5d87bd07f561d403a678c6bd8b9f064772b5489d6d828918ee9e034fef331a86e129619d12338fa63bd84e1daeb2c3e9b847aa828bd10eba784f6ecd533c1a37d8867091f31ea028668fc3add25ed7503a923ca663f9429fe2e32a4cdfb62fcfb6334c365cc01b73aeb52b5f76b60e7d88a1c934b17fbc81268be65cd10176fd65f5474be2202d31d49b36263b52dbfec9ce9b339481ec59ae15076ba8ca41dc4542f27d408fe4440c66359b826108162fa6a3fee5dea3b7ebc777e1736519e2a3792aa51d3405a7e84dc4ca705bd44033aa950b148e5449d5b068be2ce92f1166115669f9467c2e3c75509b9db1f5aa7a3d9780233aedf362e4d305778b4b41d7ccc05e506b0644b8ef1259681088afcda8f74a6d4eac7fe5a93280c4803db399c5b13b89445143ad784294a64e0ac07584a956f7c36a12433d1b97081a7fb4bc98157b4be2a805ab08a8ce7226f60a6f4daab5e3a2f5f909ec8891d0296aed2020c6645b3aa3def5aed79af2f6324e091fac94176b57c9d69eace38802bf09c6a380ceae13c47676890bc971a02f123b309bfff92a2616416497cacd04748b9d0665a0ff034d9c37ccffd0e3ca1b6f44f0f25745884c452ca649a90f37a349218d7b01edb260163abba6fd8e9a479d6a18a842ed425df4fc40f9839893419bd0f987145bf832cbfb65908a55431de3227638f016f3ee25ae8e0c1cf1cb2fa051bb5e73cce573e6bf88f1be40d9d7176142231cbb4bf75994176b3b53d0e4c3df553c784281c8c8d863be6e2a796f9fa95cd7e9f6342c9de5d68a4e6b9f2fe406e0e75320ff8854b5e6a8e70763ff774847db773e954deb6bc99d13bb08df7295e1279683718ababfe36bece20659908f65d3200224479ada94cc83118367b60f429a0a204e25e77487ec2e40149e9f34691d9247856e9047ba35dfd2ac5b8f2f8dacfa05a0ef4abf75208dc9a6e4e1b2524e6da31f9ca255abc3d2f64fa4bf7eda5b770dc83395621db232005af7b874feb8047b233ada47696f8fca2e4ecfbdca7525149107321bd47bdc3d4ee30c3457640735a725906f4ef9b9b5e20b33622c241794e9d3610db4b5bf44db843c9c7cce5f49fcf4ecf4f89976775c4bded89b2ee075d575fbb4fd0bb41e54efe42ab2651798a3c4eaeee4bb98f4d8ec0c99435111134357f26f15c69e89662128ce341176d043572e788fd55b3d38da5a4b9d0370f56f2afc4c3be76c001cec7d6d149a9eb72dc2cedd76b77d8e682326e34c7f461ee21a299cc689cc57c1e467e71ca05e3eb4563b190ad11aa0373cd7082e92abe8b9e7ab941a6fc833efe36a3a712e44a6f7bb3e3614e26797294af8ceace4777c6f7854c13750e36db06c985f6b7a818af8483a24b9432c353ce8fce5b4cd722618bfb8d506fb20d0c348c50da057622afc8fcce468eb121a25afd6e04fa926ee2a10b3e9389f53f82eda9c3c7ce2fd001b2f41e383f90d8b6a890ef450d7b1a536e532cfd20b826e1bdb0dce25d50c7de8e0db8ded72ba3cf3edd55060f26d894a479e1f067891b384e2cf623cc0f7b70693cb8979b48cd119a80a72d6dca42b8432129fb87f017a7de8501e56d46ba5f495b76a04e9d67e47a040204e11138efca05e592122ad93c7d2d1267d648b2855f1166c5f248973944b64763b94b6c3956a885200954b7451a4b63c0645112230265e712b922c0a9a1ebff88ec4b352f2cbc4e1c1a0d732679f3e100c3b05130f3705fa0ddc082e06858524d1b5a94ec62c363e865872223ec5f644c336c5b6725ae511348aa9a2ef73ade3a6d87a2b25dd81746155d9c5c74a753ecd44700827570965204f200687e74ed21f72b9f5c7785d10c37339480996eb517cdf98183654986483b778ec93e96b6bccb265cc84422d2d92f7b9301d2b6291534ce0041fe357e4b9ee2b4a0bbe88d0999c910aedb94b5cc799e34df6dd6d92e9e89635b45578957f0d17ef0de4e04f31db4cea541c31be0b448e09aa694e8ed4b8e37c3d1c94d31b2e6e66b7e9838ae5fc8c8ddc1581b3ec80be245ac5e1ff1dde6e88eb5869c886b1e60d24498252135ed6092b22ce0fcf66cde7d24395168bd606d462a3d5ad2834e5061b5ebf555cbc822040603bf43cb2ad75d6c6efd38abf995a3cb30622b9ba49310631c2a56cf585ee3ddcd50627455e593f3679ceea9a40033dde27849d6c7a787ec0a303b648fce4cbc639f07c78dceedf7b2ce2ce19c536a0870f6611d82eed7c0da3267f5997f7b0c6d4a3be17e12ff290123075b8c42c702daf70ddfeac053553050b5bdfadbbe055fd59bf52b7d8243fb0df8da460ebf759f7e841a2bf7683563ffe483dff69f47c57c8692944a188442a532ba2d455d84edcba8f3bd55172e569791e6f5b53368899918f76a7c487db2d37647cd267c19bcff9f78c8930f227482d8c02ba1ce7df17335e8a08172f792afd9bc996c85977a6792d4cac390cdeb51036fbc11c4e0f179d54dc9fb36b1e764c5cfb03a2d79c37b40aae1860d742a773133ce4759f1e7ce7935010a1b763f023589fb65dbdf8c541416c3ace3d1666dff277e066d3cc12db952b229e59a3b2c7929d2529fac70db268ec41b389268f873bde2af77ed24553646a9c1d79dd22eed335bef3ebe7b0234e36f798e0c6337bc11781149d8c295262e3830405c4752fa9a91335acc7e1ecaaa4f9190ac78a3047b2a1b81a751c55cdc9fd1712de461711d884f3b39082432bffbaa90ccca64c295c50daffcf62ccc9f3356fc40381ff635ab754c04fa4a240fa44f2ab30d9a55a289eb6ea475f1a6fc70c7bd498ca5d501c7921b151d823ed23307d33469eae513cfa973d5ad54d04f6018d2c99de02de0059e8645a140d52c43c2281024c9da696f5fce458f6cfc214dbe909314443e208d260c6550620ccdd6d390c8ea0250e08c2fbfdbac8254af358efe98bd93937555bdd75c4cdbdead4bae8b5d81e685088b0e8944bcd9c4f10de1b5614d0d5744634ecb4117390cab6057e8c1d1143a910b613a71c88c5268e377f2668cbcd0a3cd145eae867173eff2f2fa9dc953e140c64e478413b6ef0342d7c4cb58ac5ab8a18fbf96a7436e9875c4eaeccb3bf9987846fa360ba0a6dba935d2442ff5eb8a4635a34132d9e99910853c57d89ec8a4f5fdb2e02baf5b76bcd61ba782659184f8c71b406d3efb9045f1d56d13f18edfdf319095a1f4766a21595327e4116351a17beaea26bcd319858b3b4951a9a9380623bb932e8a3b56e0c5596f9f3bfce0c05a95f3f5165439309197b0cabb4cf2840f6120ee4e4393875c12ec807ce6d556e0085f91b25372a9b1666ca0652fb543b62eac338d784052341e825496e606cf3c5f2cc9afe6d20fdef1d4deac13713dd5d639593662464cfa065fd9ee33e3ea619596746247c3c3f7244fca2f114bbac35f30454af9c585581021e13d7432597ebc2a682874d7ba416f63739604c7be0d32a16504ae2eb5a808d499f11fca2b4d81c4ad82e965c816873deaa42832e74d44d7eafdb2bfd792530f2386a4ad73ef17afab72460998853cdcc5651213e8ef1d5ce7a50a4189d27f9e35d88e9ce50cc4c05fee405fd18c77833a7da2722cb8594fd4aea348753ed50b98a45b4d3a1868d69c0f1dbd326dc48f984b2a19c857a9e7d3f93f0c80c4179e99db07bcf7f2d0925efee01b562d6efa2c7d8edbfef0ccfbfefb8ee35f73868d5d8901df103f868512b8cb696e03c1ce6c126df26158b2557a303c5df63d923653c970ce1a6da8222e610185b66b93a0322f82b788f97b1e80c5a3434e523bacad6d70f49f7e5e1801401d31deb6d070dca777b6a82f8ad6f0d14fb3c0cbb945688e1c039d893a4a275c5ce8974e48f585054bdf0d32ef1cadab6547a2d52ac7f20820829f0c79c86f622d023c3a0e6b3dd704c232731a80f9cd08fd60574b3501a24a7afe9bf9b8536074dcc84b253072e4377ebcd3d8eeab362eea1c155ec41901fff28376167853098de98727513d38952d2dfdbe117fe5d92731c3b4e47a81fe4a494ab4d2b6cfaa58bce88a7e9318100130b2c9d0830f7e38a4cc2846f70ee4dbd3273188605bb55b2df9cf885eeb703b203c62383c8e478fd278dbbda0390d80ffda11b80087356612be31332ccc7432e8b82dc1d429507f54481b357330c970e8668aab20f89ab941a5f77061de1d9a1b6151eda8e58dabadbbb61cc061b0347ce727a728ef42dfa4fe5e8da8de96ba298d68314cb51bc295e0df0ec916099b898ffa8ca230c9c21665175f321291958073ecbe7558a9bb9801af96396f1ccaedc54590dc5f8b75e9ec12628a036d229f26ed1bcfb458b1a5c1a61954a3671ace785b75061979c90af65f346997745a373c183f666c3e734b80d6e41fb0d9e0d33644517cd9467079159d0c0d286190e098d5c17dc19fdbaf85bc60563f8b1ee6e14c32bc467e02d2bb0e7805a22b208aae70f70d8d8b81d11e963e23e30120149bfd5aec15ea40299daa0cbc1e613e41c2dd128a10f3e0411c053938b6de2852a3014b0d892ff7317b5c01b1684cfcbd6ad89293af5368ca17b102d40783031c6f1614d5d833ac8ee9ee4f4c68630adecc18f857ebabbdbb57ef139647d7f332cfbc7dfeed9960abe37e21626e9929b2dbcdb149ec9f1157710912772d523e1f6cdc409ce32b76caef741e6779de74a3a36dd849e20ac692b859ba85ef976d8a4eff86b1ac386f5277b8a4a16f05e2ec38369379f3f202d6e63dd3e2f30903aa5832e80f79fe364ef82446a97c751b37b22b18f48a7b2af44281386cb1d9231de1cc3ea8a77253750d4d4c2e439bcffffad9051f50f824385624eb79ff286a6d894d1ac64cbc2e573d89addbbfb841d7b4bc14c1af2290f239ce64b889b1b05fbf6785bf2881097503a0376b25c330025cb4c9ee86a72ae86e57486a1d33887ab2c46ae5749ff46490c2a3bec7047084e1e187257e8683c74156c16b8a19fac5dd0d62723d92bae6cde4bf1687f78952be2d67982b839db9515dccf9d0280011afde3b94bd932fe3fee9346c0edad84a0b1138a7c6bde81e0d270d4694bbb3dc3bbb2874e8b36e4270fbf83e21407cea0d35a938022cbadca27d784fe3b09842f6ee643833da09aba5e739de5ddbd3428e819a8cfa8f1b496365c85f7d93dd1bac2c776be69f21fbda76e477842a1a70e3e6749def4232d08261d7b9979baf161d1257fe8b7d669b31ac482d6cdd7ab249fce9e10e7c23b51a8a6289a48907e110dfc4bc1acdd67cc208cb5b8f295b849227b1217d9ee594a2fe7a7c1e5ca40c9370419687475d5a24a4e2e7e784e7140283b674c8cead5804e5412a7547ebea83dbfdd18b8159294e0f7c7360c0cec50e7e47dd5641a27b748c7f29ac56818fecf3f9f3ccbaf157654fbdb785b92553b17dc2cf05b54c439beda0340238d076941b8decb07bccec560221dadcead2e0030b8bdf4e33e07079b39b882d11766f8257eee4e47b9c777fef18124ab1c4ad642209fa6c477c2d66b151a2f4071b0820c6b5813bff72c7ec5ff22d50e4d09c387c6d44bee7eaedf0b2341dde6be3e19239d3e59a30dd665fb43677c8dfe67fcef7610bc683a5e4fb0198f78ab5b388d8434a81201af2942decb0c2a5d32b13b4e9911a299e8b5ee937186f880fa3b1b63a5f6de168d03292028c6b93aecd0677eacd15366a95f156e38960adfd1891cf9bbc72d3a9c4cf6d5cb303ec240cef3b098764a9266cbb9544693b0b1974621d4916f94b9da7dcad9642c1e1d210e88ee33556fad660604b18ebf0392faf50bb8f6a724418402764b88f65f22e80439b9a2806d7131abe74613ac8a1f0b302394def5f845f170700b455a52623f8da2a8511231b4e0c852c66bc02f79c7cec1d8d1dd44e7e6051d02008dd7bda6a05f5a5fdcd152f663b7a9d0fe37f193183beac897012534eec275aa3a3e45c63c69b25f7c53a1f3bff29ba4590c2d1ea08b1bc21fea48fb5002b735b1a42e7824644db18c11fcbbaedf9b7448ffd0b76c6ba07d4a774f69a9b7d864b13e4a0bfb055e11dea535857efdddd70924cce74d4c9363e9c21698dc219d1d3c1674068545a692d0c4b2e548c953406187ee625a3b0ef7ffa501945ce206340057be9eab4a08997693c3adffe4ce4f046b426980129c3053fa0b5d0a7821265fcaae5f5f175f5b0b2ea6dbef1913e7cd39bc65e7abc63d1ac881987a115b9f1c6c697cb2cf0b66521f3e90526dc4901e7b3d6f53ec4f948a493b8289aaf2654579b6801c8402da6a5401e9b4b80f73f2c8eb41d53ae0d14905d25d1aed213173aad3cd766e038d165a639a53b60a15afd58635217601732d80b6ac253dd1cb33be4725880fc6cea697acf88276472e682a099b436550e0e03536a53998a153f63dcde22a511179556478a300ac77e19caf50183d1ed7f2d2e55dc972aa801c636df97502005c109049f8698f666ee98c77019241586e128fda5a340eef3a0cfc386da2cb69076e60185088b7de8de29cce1107fb6ee51df5aaab114917d5ab88fbcbe4f6a546c42a2b6498fd9ba542a495d20fadfc751009aece5e8261ae7072915b89c54009c53e212df02728981ff7a6a47dc8f163a21dbde06d76121e105f4d511d46bce2813ef7175bfd800ffceb50f2526c8a3689565a277f4724f184cca647a4d1b15ca1f5a33b5ac0cca6e25371a73fbcd761c0710c27053dd1e9fd128683b7324d4199d8ae2bb4d4de9df861c9674cb6fe60b665300a6cb24fbc23b4a556374f3d4898a19593ecfb75635f7ec573012af6aecae91dca02f04ccc80e7007abb1d5da04553ae014979590e24d2487a64287ddc8641b25115972d2a8ee41c6d71832fbf59cb07b1b8237f72c0b961d497e1cb0f00f0f7aa0315d377d112b441f84dd749c03d14f43fad12eb5f6bb5849d190081bfdffb4b0548f30c102653fefb8829f8bb686bfa144ab792474eb5be35182a6c6e898637a2f906f89085f49546245a69729252f04d04cc55124ed238ed077ea0cee46d1aaf5c9ca84cff31eff6f878b3efb5ca58778b24fbb0966e3416f41b2d3eac5fb8711049ffb048f8c799a9485d127ba0f4cbef9acde576f5016940ad3bd73df0d48ba1e1004ef5f2abe672bd0f33ff46787d5eab759a6c055ab8b3049c7475c017a1602c7879d72092270967d23ea935cfc106a4650f6e5fbcf404df66f887018a2edf7ee6a7406bc1fa731c996a71948c66be49fa314963b028f0be89d589f3f679b3f74e07e07ab28c2d7d4796fc56746e4d7c02ab70e9fe11e69582db984542394fdc727d60cc12c9f423f1f229a493a140a5e7ae1b7cf9338cd57a47840bbd97917e1aa378b4aa1b0ea53f9607dcbd98a9fa82910371966099eae36b9b01177b3e945cb6397a22f1d3789ee8c9bfee95d1b8ee51109337c6ddbc435f6044ecd74066d53e8da594a39b049a613c75cb682ab5c1b0e01cae0e23eb17261ef9cec6dece86d18fc822bf83634a5c94e654e024f426db6d8cecc5bfc9c5c6921df6967f7272740584f94c5c88cee7cf50c364cbd21308d34b0de045788685f14eed0ca1071e8d29b65d4dca78f0c23233c5048c5da1af083897e57a3774bd124feafc32a1525a8c8e7c4b6bbee19928933abb59d86d3b4c9bddd5d6245e9b0a372210ed176f61dddfd2eeacdfd6dcecd9c7ef559c513e92937b918ebe7aeed95d6b33a498bebaba34d9f9904da92b8ca618a0eb072168dd2c481a468d97eec11fc427450a2308dc238b74f8c82603c2498f55b149269bf303ee7ba86e0eb0dc89f86bb5052c3ba9df4f2ad33a80794fb7ccf8175ae8c7aed21e6ae40efb6502607b372869fa96ade5eefa7de9a98bc912c0c2a0778ac82830fa858e0d97c308166349e56690543f854325002ac80a352444a0e1880479b397d00caa64fd1f1ac5772ac02e966b9fb6e5398bd9b4158d2730d7bc9bc71c575fef80c402e7ceffaeefe0140949eba8deb7ffa46c2917dc3e4d5fa6fab166b96ef25365ae2dcd0ca08a2d150b7eba8bda5545e33bdc0b506d8756089def32b797492d8ce780bdc7e30aaee1bb16e40077dca423ccb0ebd3da009087c6a27e9a3b5197e88011c2819414ab477cacb56c3ddafa1298e64c5df7e4e92cd2f26601b19c4e64d5a33dc4611cb4dc02d57a4da8e290db3344bb6f7d884db1f2565714e80e8ea3d93cb6d17c217c9f1463a42a87e4b4bf453922115ec814c6f48baa3802006de7a765ebf3de1b42285682ce879a7d0484938d45720849c41ae630c6d51c89c6f925191f8fd3d9cdbd9fb12d6ee6f7bbbeaf119ff903ad2ed0f6e858d49affce0aaefbcbf4bd390449ffd2feb7958395c99c0608520e713c922baa251b8f76f0ee0f592c8516fa31295f25c5f81d900d6f823858e7f456599d2d8a64f8955f331c4540743a597415692dbde71453d0fc44bc65e24a0887bb1005004739dbf1e2337f4f02195ec8a9a320587a5e54975e00536abb3795d20159f29f0b332b02ad7bf92d243ca621240778b049222ed44d8fef9c494ccde58e995b272e1810046789eeefcda35eea46e54337c787b67933405236100358c5993ecc82defe266e31a06c582b16b112e971a8c608cdcbfb4736093546ef296ddd3a706f73a56a57d74cc4e4757dddebb39e330da30b0ead2de9d83c449cfce3f7757abd4e1fb350a82e3306087c7f928266a45f9932c19b99d99986b0a6deac9f32c13bb91f3f05bfa9247ed3e25b311225696056db886a14630a4d6f4f97f0133cc81c00b69c98858ea363e1c22215c71377c7a798e2c95304a2b803fa6477e6cd11891abfa99d44efb0388fc0d873b8ee7c0cefc78dd84647e648fb472167454cd05fda6a1327efac3745e49d1c5c9d6ca385e48bb170f7ba65ae016fec82d32eced3d35bdcf35c960e4cd0558a1928de4ce52e2938edcdb20e89abde72635ecbeaedf896dd96eb4e778aba908876abdf319bdcdcbcdecb439f74c32cd61a5099a26f49e4725464687a158a1ebb5b1de63d26c9ac825e7204b73b3711d5e252fc260e5a6d19e7bb7c31bec1522c1ac0a0ffc5940c8e1eedbc950e4d3cb8c28ec790909ee515fba0dddc89749ddc6af7bf1a5f6b1f2b5b0d6077de7687dad10d98e791bdd35b4ef21276d4493c9fa24efb6dc226ec5f55aa7fc1dc8e1d8922a67fbdbbf16d5963469885b400e53d58c6053bb23cf54bcd247183447b6dbf326647d2536ae7779f3ed58756191c77b6117e92a8ddc09e4e9f3e1372c3c2dccc35953660dd520d79dc24f9f3991fe481b35908b490edf73d42d3ae48da17494cb86c6397da55d92c2a41b515daa79272680e3c68a8a0157e9b1ee069b50336939356fe5b184ab8746e5b1bf28ce78bd8dcdc56e8b5015a77488391c5ed3d971a2443bb82e822b7a642f607211ac4fb4e8c470be8231eb56fcec989fc933899c11379c9c3ad9470a065f0101ff"
)
// katMode is the parameter set the frozen vectors were minted under. SHA2_128s
// is the smallest FIPS 205 set, so the vector is 7856 signature bytes and
// verification is cheap enough to run over many tamper positions.
const katMode = ModeSHA2_128s
func mustHex(t *testing.T, s string) []byte {
t.Helper()
b, err := hex.DecodeString(s)
require.NoError(t, err)
return b
}
// katParts decodes the accepted vector into independently mutable copies, so a
// caller may flip a bit without disturbing the next subtest.
func katParts(t *testing.T) (pk, msg, sig []byte) {
t.Helper()
return mustHex(t, katPKHex), mustHex(t, katMsgHex), mustHex(t, katSigHex)
}
// katFrame is the exact calldata frame the frozen vector encodes to.
func katFrame(t *testing.T) []byte {
t.Helper()
pk, msg, sig := katParts(t)
return buildInput(katMode, pk, msg, sig)
}
// word is the 32-byte big-endian result the precompile returns. Comparing
// against the whole word also pins the 31 leading bytes to zero.
func word(v byte) []byte {
w := make([]byte, 32)
w[31] = v
return w
}
// call invokes the precompile with exactly the gas RequiredGas asks for, over
// the input shape the EVM actually hands a precompile: len is what the caller
// declared and paid for, and behind it lies memory the same caller filled.
// Without the poison an over-read lands on zeros and every bound below passes
// whether or not it is there, which makes the fixture the subject of the test
// instead of the parser.
func call(t *testing.T, input []byte) ([]byte, error) {
t.Helper()
in := contract.Poisoned(input, 256)
out, _, err := MagnetarVerifyPrecompile.Run(
nil, common.Address{}, ContractMagnetarVerifyAddress,
in, MagnetarVerifyPrecompile.RequiredGas(in), true,
)
return out, err
}
// TestKAT_VectorSizes pins the frozen vector against the precompile's own mode
// table AND against the sizes the library it dispatches into reports. If those
// two ever disagree, the pubKeyLen equality check admits a key the verifier
// then rejects, or a signature slice is cut at the wrong offset.
func TestKAT_VectorSizes(t *testing.T) {
pk, msg, sig := katParts(t)
pkSize, sigSize, _, m, err := getModeParams(katMode)
require.NoError(t, err)
require.Len(t, pk, pkSize)
require.Len(t, sig, sigSize)
require.Len(t, msg, 32)
require.Len(t, mustHex(t, katSigNoCtxHex), sigSize)
require.Len(t, mustHex(t, katSigSlhdsaHex), sigSize)
require.Equal(t, slhdsa.GetPublicKeySize(m), pkSize,
"precompile pubkey size disagrees with luxfi/crypto/slhdsa")
require.Equal(t, slhdsa.GetSignatureSize(m), sigSize,
"precompile signature size disagrees with luxfi/crypto/slhdsa")
// The frame the vector encodes to is exactly the offsets Run computes.
require.Len(t, katFrame(t),
ModeByte+PubKeyLenSize+pkSize+MessageLenSize+len(msg)+sigSize)
}
// TestKAT_Accept is the positive known answer: the frozen vector MUST verify
// true through the precompile, and the result MUST be the canonical ABI word.
func TestKAT_Accept(t *testing.T) {
out, err := call(t, katFrame(t))
require.NoError(t, err)
require.Equal(t, word(1), out, "frozen KAT vector must verify true at slot 0x012207")
}
// TestKAT_DomainSeparation is the cross-slot replay refusal. Both reject
// vectors are genuine FIPS 205 signatures over the same key and the same
// message -- the subtest proves that first, so the refusal cannot be blamed on
// junk bytes. They differ from the accepted vector only in the context octet
// string, and the precompile MUST refuse them.
func TestKAT_DomainSeparation(t *testing.T) {
pk, msg, sig := katParts(t)
pub, err := slhdsa.PublicKeyFromBytes(pk, slhdsa.SHA2_128s)
require.NoError(t, err)
for _, tc := range []struct {
name string
hex string
ctx []byte
}{
{"plain FIPS 205, empty context", katSigNoCtxHex, nil},
{"single-party SLH-DSA slot 0x012203", katSigSlhdsaHex, []byte("lux-evm-precompile-slhdsa-v1")},
} {
t.Run(tc.name, func(t *testing.T) {
other := mustHex(t, tc.hex)
require.NotEqual(t, sig, other,
"vector is identical to the magnetar-context signature; the test would be vacuous")
require.True(t, pub.VerifySignatureCtx(msg, other, tc.ctx),
"vector is not a genuine signature under its own context; the test would be vacuous")
out, err := call(t, buildInput(katMode, pk, msg, other))
require.NoError(t, err)
require.Equal(t, word(0), out,
"a signature minted under a different context must not verify at slot 0x012207")
})
}
}
// TestKAT_TamperSignature sweeps single-bit flips across the WOTS+, FORS and
// Merkle-authentication-path regions of the frozen signature. Every one MUST
// reject, and none may error -- an invalid signature is a false verdict, not a
// malformed frame.
func TestKAT_TamperSignature(t *testing.T) {
pk, msg, _ := katParts(t)
sigSize := len(mustHex(t, katSigHex))
for _, pos := range []int{0, 1, 31, 100, 3000, sigSize / 2, sigSize - 2, sigSize - 1} {
for _, bit := range []byte{0x01, 0x80} {
_, _, sig := katParts(t)
sig[pos] ^= bit
out, err := call(t, buildInput(katMode, pk, msg, sig))
require.NoError(t, err, "pos=%d bit=0x%02x", pos, bit)
require.Equal(t, word(0), out,
"single-bit signature tamper at pos=%d bit=0x%02x must reject", pos, bit)
}
}
}
// TestKAT_TamperPublicKey flips single bits in the FIPS 205 public key, which
// is seed || root. A flip in the root breaks the Merkle check; a flip in the
// seed changes every tweakable-hash address. Both MUST reject.
func TestKAT_TamperPublicKey(t *testing.T) {
_, msg, sig := katParts(t)
pkSize := len(mustHex(t, katPKHex))
for _, pos := range []int{0, 1, pkSize/2 - 1, pkSize / 2, pkSize - 1} {
pk, _, _ := katParts(t)
pk[pos] ^= 0x01
out, err := call(t, buildInput(katMode, pk, msg, sig))
require.NoError(t, err, "pos=%d", pos)
require.Equal(t, word(0), out, "single-bit pubkey tamper at pos=%d must reject", pos)
}
}
// TestKAT_TamperMessage is the message binding: the frozen signature MUST NOT
// verify against any message but the one it was minted over, including a
// message that is merely one byte longer or shorter.
func TestKAT_TamperMessage(t *testing.T) {
pk, _, sig := katParts(t)
for _, pos := range []int{0, 15, 31} {
_, msg, _ := katParts(t)
msg[pos] ^= 0x01
out, err := call(t, buildInput(katMode, pk, msg, sig))
require.NoError(t, err, "pos=%d", pos)
require.Equal(t, word(0), out, "single-bit message tamper at pos=%d must reject", pos)
}
_, msg, _ := katParts(t)
for _, alt := range [][]byte{
msg[:len(msg)-1],
append(append([]byte(nil), msg...), 0x00),
{},
} {
out, err := call(t, buildInput(katMode, pk, alt, sig))
require.NoError(t, err, "len=%d", len(alt))
require.Equal(t, word(0), out, "message of length %d must reject", len(alt))
}
}
// TestKAT_ZeroPublicKey feeds an all-zero public key of the correct length. A
// FIPS 205 public key is an unstructured seed || root pair, so decoding
// succeeds and the refusal has to come from the verifier itself.
func TestKAT_ZeroPublicKey(t *testing.T) {
pk, msg, sig := katParts(t)
zero := make([]byte, len(pk))
_, err := slhdsa.PublicKeyFromBytes(zero, slhdsa.SHA2_128s)
require.NoError(t, err, "an all-zero pubkey decodes; the refusal must come from the verifier")
out, err := call(t, buildInput(katMode, zero, msg, sig))
require.NoError(t, err)
require.Equal(t, word(0), out, "all-zero public key must not verify")
}
// TestKAT_CrossParameterSet is parameter-set confusion. SHA2-128s and
// SHAKE-128s have byte-identical wire sizes -- 32-byte key, 7856-byte
// signature -- so the mode byte is the ONLY thing that routes the frame to the
// right hash family. A SHA2 vector submitted as SHAKE reaches the verifier and
// MUST come back false. Every other parameter set differs in at least one
// size, so those frames are refused by the length checks before the verifier
// ever runs.
func TestKAT_CrossParameterSet(t *testing.T) {
pk, msg, sig := katParts(t)
t.Run("same sizes, wrong hash family", func(t *testing.T) {
pkSize, sigSize, _, _, err := getModeParams(ModeSHAKE_128s)
require.NoError(t, err)
require.Equal(t, len(pk), pkSize, "the confusion test needs identical wire sizes")
require.Equal(t, len(sig), sigSize, "the confusion test needs identical wire sizes")
out, err := call(t, buildInput(ModeSHAKE_128s, pk, msg, sig))
require.NoError(t, err)
require.Equal(t, word(0), out,
"a SHA2-128s signature must not verify as SHAKE-128s")
})
for _, mode := range []uint8{
ModeSHA2_128f, ModeSHA2_192s, ModeSHA2_192f, ModeSHA2_256s, ModeSHA2_256f,
ModeSHAKE_128f, ModeSHAKE_192s, ModeSHAKE_192f, ModeSHAKE_256s, ModeSHAKE_256f,
} {
t.Run(ModeName(mode), func(t *testing.T) {
out, err := call(t, buildInput(mode, pk, msg, sig))
require.Error(t, err, "mismatched sizes must be refused, not verified")
require.ErrorIs(t, err, ErrInvalidInputLength)
require.Nil(t, out)
})
}
}