From 3ddafceb9afd9d493b927bc91dae324225ed8e32 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Sat, 10 Jan 2026 13:03:36 -0500 Subject: [PATCH 01/10] txgraph: initialize Ref in AddTransaction (preparation) Instead of returning a TxGraph::Ref from TxGraph::AddTransaction(), pass in a TxGraph::Ref& which is updated to refer to the new transaction in that graph. This cleans up the usage somewhat, avoiding the need for dummy Refs in CTxMemPoolEntry constructor calls, but the motivation is that a future commit will allow a callback to passed to MakeTxGraph to define a fallback order on the transaction objects. This does not work when a Ref is created separately from the CTxMemPoolEntry it ends up living in, as passing the newly-created Ref to the callback would be UB before it's emplaced in its final CTxMemPoolEntry. --- src/bench/blockencodings.cpp | 2 +- src/bench/mempool_ephemeral_spends.cpp | 2 +- src/bench/mempool_eviction.cpp | 2 +- src/bench/mempool_stress.cpp | 2 +- src/bench/rpc_mempool.cpp | 2 +- src/bench/txgraph.cpp | 5 +++-- src/kernel/mempool_entry.h | 5 ++--- src/test/fuzz/txgraph.cpp | 13 ++++++------ src/test/fuzz/util/mempool.cpp | 2 +- src/test/txgraph_tests.cpp | 29 +++++++++++++------------- src/test/util/txmempool.cpp | 2 +- src/txgraph.cpp | 15 ++++++------- src/txgraph.h | 13 ++++++------ src/txmempool.cpp | 5 +++-- 14 files changed, 49 insertions(+), 50 deletions(-) diff --git a/src/bench/blockencodings.cpp b/src/bench/blockencodings.cpp index 3f6be56b464..ce968dbc651 100644 --- a/src/bench/blockencodings.cpp +++ b/src/bench/blockencodings.cpp @@ -22,7 +22,7 @@ static void AddTx(const CTransactionRef& tx, const CAmount& fee, CTxMemPool& pool) EXCLUSIVE_LOCKS_REQUIRED(cs_main, pool.cs) { LockPoints lp; - TryAddToMempool(pool, CTxMemPoolEntry(TxGraph::Ref(), tx, fee, /*time=*/0, /*entry_height=*/1, /*entry_sequence=*/0, /*spends_coinbase=*/false, /*sigops_cost=*/4, lp)); + TryAddToMempool(pool, CTxMemPoolEntry(tx, fee, /*time=*/0, /*entry_height=*/1, /*entry_sequence=*/0, /*spends_coinbase=*/false, /*sigops_cost=*/4, lp)); } namespace { diff --git a/src/bench/mempool_ephemeral_spends.cpp b/src/bench/mempool_ephemeral_spends.cpp index 2f89f0da208..f0d8eb0bea7 100644 --- a/src/bench/mempool_ephemeral_spends.cpp +++ b/src/bench/mempool_ephemeral_spends.cpp @@ -29,7 +29,7 @@ static void AddTx(const CTransactionRef& tx, CTxMemPool& pool) EXCLUSIVE_LOCKS_R unsigned int sigOpCost{4}; uint64_t fee{0}; LockPoints lp; - TryAddToMempool(pool, CTxMemPoolEntry(TxGraph::Ref(), + TryAddToMempool(pool, CTxMemPoolEntry( tx, fee, nTime, nHeight, sequence, spendsCoinbase, sigOpCost, lp)); } diff --git a/src/bench/mempool_eviction.cpp b/src/bench/mempool_eviction.cpp index ad3ab08a994..37bb7215be0 100644 --- a/src/bench/mempool_eviction.cpp +++ b/src/bench/mempool_eviction.cpp @@ -27,7 +27,7 @@ static void AddTx(const CTransactionRef& tx, const CAmount& nFee, CTxMemPool& po bool spendsCoinbase = false; unsigned int sigOpCost = 4; LockPoints lp; - TryAddToMempool(pool, CTxMemPoolEntry(TxGraph::Ref(), + TryAddToMempool(pool, CTxMemPoolEntry( tx, nFee, nTime, nHeight, sequence, spendsCoinbase, sigOpCost, lp)); } diff --git a/src/bench/mempool_stress.cpp b/src/bench/mempool_stress.cpp index 9cddeb7815f..1f582081ea9 100644 --- a/src/bench/mempool_stress.cpp +++ b/src/bench/mempool_stress.cpp @@ -29,7 +29,7 @@ static void AddTx(const CTransactionRef& tx, CTxMemPool& pool, FastRandomContext bool spendsCoinbase = false; unsigned int sigOpCost = 4; LockPoints lp; - TryAddToMempool(pool, CTxMemPoolEntry(TxGraph::Ref(), tx, det_rand.randrange(10000)+1000, nTime, nHeight, sequence, spendsCoinbase, sigOpCost, lp)); + TryAddToMempool(pool, CTxMemPoolEntry(tx, det_rand.randrange(10000)+1000, nTime, nHeight, sequence, spendsCoinbase, sigOpCost, lp)); } struct Available { diff --git a/src/bench/rpc_mempool.cpp b/src/bench/rpc_mempool.cpp index b27a7e72cc4..f319c961a04 100644 --- a/src/bench/rpc_mempool.cpp +++ b/src/bench/rpc_mempool.cpp @@ -22,7 +22,7 @@ static void AddTx(const CTransactionRef& tx, const CAmount& fee, CTxMemPool& pool) EXCLUSIVE_LOCKS_REQUIRED(cs_main, pool.cs) { LockPoints lp; - TryAddToMempool(pool, CTxMemPoolEntry(TxGraph::Ref(), tx, fee, /*time=*/0, /*entry_height=*/1, /*entry_sequence=*/0, /*spends_coinbase=*/false, /*sigops_cost=*/4, lp)); + TryAddToMempool(pool, CTxMemPoolEntry(tx, fee, /*time=*/0, /*entry_height=*/1, /*entry_sequence=*/0, /*spends_coinbase=*/false, /*sigops_cost=*/4, lp)); } static void RpcMempool(benchmark::Bench& bench) diff --git a/src/bench/txgraph.cpp b/src/bench/txgraph.cpp index 078f77b4256..7257a043777 100644 --- a/src/bench/txgraph.cpp +++ b/src/bench/txgraph.cpp @@ -67,7 +67,7 @@ void BenchTxGraphTrim(benchmark::Bench& bench) for (int chaintx = 0; chaintx < NUM_TX_PER_TOP_CHAIN; ++chaintx) { int64_t fee = rng.randbits<27>() + 100; FeePerWeight feerate{fee, 1}; - top_refs.push_back(graph->AddTransaction(feerate)); + graph->AddTransaction(top_refs.emplace_back(), feerate); // Add internal dependencies linking the chain transactions together. if (chaintx > 0) { graph->AddDependency(*(top_refs.rbegin()), *(top_refs.rbegin() + 1)); @@ -85,7 +85,8 @@ void BenchTxGraphTrim(benchmark::Bench& bench) // Construct the transaction. int64_t fee = rng.randbits<27>() + 100; FeePerWeight feerate{fee, 1}; - auto bottom_tx = graph->AddTransaction(feerate); + TxGraph::Ref bottom_tx; + graph->AddTransaction(bottom_tx, feerate); // Determine the number of dependencies this transaction will have. int deps = std::min(NUM_DEPS_PER_BOTTOM_TX, top_components.size()); for (int dep = 0; dep < deps; ++dep) { diff --git a/src/kernel/mempool_entry.h b/src/kernel/mempool_entry.h index 58824f7a80c..dd0c23a2cde 100644 --- a/src/kernel/mempool_entry.h +++ b/src/kernel/mempool_entry.h @@ -84,12 +84,11 @@ private: public: virtual ~CTxMemPoolEntry() = default; - CTxMemPoolEntry(TxGraph::Ref&& ref, const CTransactionRef& tx, CAmount fee, + CTxMemPoolEntry(const CTransactionRef& tx, CAmount fee, int64_t time, unsigned int entry_height, uint64_t entry_sequence, bool spends_coinbase, int64_t sigops_cost, LockPoints lp) - : TxGraph::Ref(std::move(ref)), - tx{tx}, + : tx{tx}, nFee{fee}, nTxWeight{GetTransactionWeight(*tx)}, nUsageSize{RecursiveDynamicUsage(tx)}, diff --git a/src/test/fuzz/txgraph.cpp b/src/test/fuzz/txgraph.cpp index 195c2e05025..6d5ac88218d 100644 --- a/src/test/fuzz/txgraph.cpp +++ b/src/test/fuzz/txgraph.cpp @@ -137,15 +137,16 @@ struct SimTxGraph return simmap[pos].get(); } - /** Add a new transaction to the simulation. */ - void AddTransaction(TxGraph::Ref&& ref, const FeePerWeight& feerate) + /** Add a new transaction to the simulation and the specified real graph. */ + void AddTransaction(TxGraph& txgraph, const FeePerWeight& feerate) { assert(graph.TxCount() < MAX_TRANSACTIONS); auto simpos = graph.AddTransaction(feerate); real_is_optimal = false; MakeModified(simpos); assert(graph.Positions()[simpos]); - simmap[simpos] = std::make_shared(std::move(ref)); + simmap[simpos] = std::make_shared(); + txgraph.AddTransaction(*simmap[simpos], feerate); auto ptr = simmap[simpos].get(); simrevmap[ptr] = simpos; // This may invalidate our cached oversized value. @@ -455,10 +456,8 @@ FUZZ_TARGET(txgraph) size = provider.ConsumeIntegralInRange(1, 0xff); } FeePerWeight feerate{fee, size}; - // Create a real TxGraph::Ref. - auto ref = real->AddTransaction(feerate); - // Create a shared_ptr place in the simulation to put the Ref in. - top_sim.AddTransaction(std::move(ref), feerate); + // Create the transaction in the simulation and the real graph. + top_sim.AddTransaction(*real, feerate); break; } else if ((block_builders.empty() || sims.size() > 1) && top_sim.GetTransactionCount() + top_sim.removed.size() > 1 && command-- == 0) { // AddDependency. diff --git a/src/test/fuzz/util/mempool.cpp b/src/test/fuzz/util/mempool.cpp index 241a4d559c7..a6a28f94006 100644 --- a/src/test/fuzz/util/mempool.cpp +++ b/src/test/fuzz/util/mempool.cpp @@ -27,5 +27,5 @@ CTxMemPoolEntry ConsumeTxMemPoolEntry(FuzzedDataProvider& fuzzed_data_provider, const auto entry_height{fuzzed_data_provider.ConsumeIntegralInRange(0, max_height)}; const bool spends_coinbase = fuzzed_data_provider.ConsumeBool(); const unsigned int sig_op_cost = fuzzed_data_provider.ConsumeIntegralInRange(0, MAX_BLOCK_SIGOPS_COST); - return CTxMemPoolEntry{TxGraph::Ref(), MakeTransactionRef(tx), fee, time, entry_height, entry_sequence, spends_coinbase, sig_op_cost, {}}; + return CTxMemPoolEntry{MakeTransactionRef(tx), fee, time, entry_height, entry_sequence, spends_coinbase, sig_op_cost, {}}; } diff --git a/src/test/txgraph_tests.cpp b/src/test/txgraph_tests.cpp index 26cf2b3a970..31fefd9ce18 100644 --- a/src/test/txgraph_tests.cpp +++ b/src/test/txgraph_tests.cpp @@ -46,11 +46,11 @@ BOOST_AUTO_TEST_CASE(txgraph_trim_zigzag) refs.reserve(NUM_TOTAL_TX); // First all bottom transactions: the i'th bottom transaction is at position i. for (unsigned int i = 0; i < NUM_BOTTOM_TX; ++i) { - refs.push_back(graph->AddTransaction(FeePerWeight{200 - i, 100})); + graph->AddTransaction(refs.emplace_back(), FeePerWeight{200 - i, 100}); } // Then all top transactions: the i'th top transaction is at position NUM_BOTTOM_TX + i. for (unsigned int i = 0; i < NUM_TOP_TX; ++i) { - refs.push_back(graph->AddTransaction(FeePerWeight{100 - i, 100})); + graph->AddTransaction(refs.emplace_back(), FeePerWeight{100 - i, 100}); } // Create the zigzag dependency structure. @@ -109,9 +109,9 @@ BOOST_AUTO_TEST_CASE(txgraph_trim_flower) refs.reserve(NUM_TOTAL_TX); // Add all transactions. They are in individual clusters. - refs.push_back(graph->AddTransaction({1, 100})); + graph->AddTransaction(refs.emplace_back(), {1, 100}); for (unsigned int i = 0; i < NUM_TOP_TX; ++i) { - refs.push_back(graph->AddTransaction(FeePerWeight{500 + i, 100})); + graph->AddTransaction(refs.emplace_back(), FeePerWeight{500 + i, 100}); } graph->SanityCheck(); @@ -196,8 +196,8 @@ BOOST_AUTO_TEST_CASE(txgraph_trim_huge) // Use random fees, size 1. int64_t fee = rng.randbits<27>() + 100; FeePerWeight feerate{fee, 1}; - top_refs.push_back(graph->AddTransaction(feerate)); - // Add internal dependencies linked the chain transactions together. + graph->AddTransaction(top_refs.emplace_back(), feerate); + // Add internal dependencies linking the chain transactions together. if (chaintx > 0) { graph->AddDependency(*(top_refs.rbegin()), *(top_refs.rbegin() + 1)); } @@ -215,7 +215,8 @@ BOOST_AUTO_TEST_CASE(txgraph_trim_huge) // Construct the transaction. int64_t fee = rng.randbits<27>() + 100; FeePerWeight feerate{fee, 1}; - auto bottom_tx = graph->AddTransaction(feerate); + TxGraph::Ref bottom_tx; + graph->AddTransaction(bottom_tx, feerate); // Determine the number of dependencies this transaction will have. int deps = std::min(NUM_DEPS_PER_BOTTOM_TX, top_components.size()); for (int dep = 0; dep < deps; ++dep) { @@ -271,7 +272,7 @@ BOOST_AUTO_TEST_CASE(txgraph_trim_big_singletons) // The 88th transaction is oversized. // Every 20th transaction is oversized. const FeePerWeight feerate{500 + i, (i == 88 || i % 20 == 0) ? MAX_CLUSTER_SIZE + 1 : 100}; - refs.push_back(graph->AddTransaction(feerate)); + graph->AddTransaction(refs.emplace_back(), feerate); } graph->SanityCheck(); @@ -334,23 +335,23 @@ BOOST_AUTO_TEST_CASE(txgraph_chunk_chain) // everytime adding a transaction, test the chunk status // [A] - refs.push_back(graph->AddTransaction(feerateA)); + graph->AddTransaction(refs.emplace_back(), feerateA); BOOST_CHECK_EQUAL(graph->GetTransactionCount(TxGraph::Level::TOP), 1); block_builder_checker({{&refs[0]}}); // [A, B] - refs.push_back(graph->AddTransaction(feerateB)); + graph->AddTransaction(refs.emplace_back(), feerateB); graph->AddDependency(/*parent=*/refs[0], /*child=*/refs[1]); BOOST_CHECK_EQUAL(graph->GetTransactionCount(TxGraph::Level::TOP), 2); block_builder_checker({{&refs[0]}, {&refs[1]}}); // [A, BC] - refs.push_back(graph->AddTransaction(feerateC)); + graph->AddTransaction(refs.emplace_back(), feerateC); graph->AddDependency(/*parent=*/refs[1], /*child=*/refs[2]); BOOST_CHECK_EQUAL(graph->GetTransactionCount(TxGraph::Level::TOP), 3); block_builder_checker({{&refs[0]}, {&refs[1], &refs[2]}}); // [ABCD] - refs.push_back(graph->AddTransaction(feerateD)); + graph->AddTransaction(refs.emplace_back(), feerateD); graph->AddDependency(/*parent=*/refs[2], /*child=*/refs[3]); BOOST_CHECK_EQUAL(graph->GetTransactionCount(TxGraph::Level::TOP), 4); block_builder_checker({{&refs[0], &refs[1], &refs[2], &refs[3]}}); @@ -383,7 +384,7 @@ BOOST_AUTO_TEST_CASE(txgraph_staging) // everytime adding a transaction, test the chunk status // [A] - refs.push_back(graph->AddTransaction(feerateA)); + graph->AddTransaction(refs.emplace_back(), feerateA); BOOST_CHECK_EQUAL(graph->HaveStaging(), false); BOOST_CHECK_EQUAL(graph->GetTransactionCount(TxGraph::Level::TOP), 1); @@ -392,7 +393,7 @@ BOOST_AUTO_TEST_CASE(txgraph_staging) BOOST_CHECK_EQUAL(graph->GetTransactionCount(TxGraph::Level::TOP), 1); // [A, B] - refs.push_back(graph->AddTransaction(feerateB)); + graph->AddTransaction(refs.emplace_back(), feerateB); BOOST_CHECK_EQUAL(graph->GetTransactionCount(TxGraph::Level::MAIN), 1); BOOST_CHECK_EQUAL(graph->GetTransactionCount(TxGraph::Level::TOP), 2); BOOST_CHECK_EQUAL(graph->Exists(refs[0], TxGraph::Level::TOP), true); diff --git a/src/test/util/txmempool.cpp b/src/test/util/txmempool.cpp index a019c830e1e..3c7eb87ccc2 100644 --- a/src/test/util/txmempool.cpp +++ b/src/test/util/txmempool.cpp @@ -38,7 +38,7 @@ CTxMemPoolEntry TestMemPoolEntryHelper::FromTx(const CMutableTransaction& tx) co CTxMemPoolEntry TestMemPoolEntryHelper::FromTx(const CTransactionRef& tx) const { - return CTxMemPoolEntry{TxGraph::Ref(), tx, nFee, TicksSinceEpoch(time), nHeight, m_sequence, spendsCoinbase, sigOpCost, lp}; + return CTxMemPoolEntry{tx, nFee, TicksSinceEpoch(time), nHeight, m_sequence, spendsCoinbase, sigOpCost, lp}; } std::optional CheckPackageMempoolAcceptResult(const Package& txns, diff --git a/src/txgraph.cpp b/src/txgraph.cpp index f60d8ca2a66..d9f5900f306 100644 --- a/src/txgraph.cpp +++ b/src/txgraph.cpp @@ -753,7 +753,7 @@ public: // Implementations for the public TxGraph interface. - Ref AddTransaction(const FeePerWeight& feerate) noexcept final; + void AddTransaction(Ref& arg, const FeePerWeight& feerate) noexcept final; void RemoveTransaction(const Ref& arg) noexcept final; void AddDependency(const Ref& parent, const Ref& child) noexcept final; void SetTransactionFee(const Ref&, int64_t fee) noexcept final; @@ -2115,20 +2115,19 @@ void TxGraphImpl::MakeAllAcceptable(int level) noexcept GenericClusterImpl::GenericClusterImpl(uint64_t sequence) noexcept : Cluster{sequence} {} -TxGraph::Ref TxGraphImpl::AddTransaction(const FeePerWeight& feerate) noexcept +void TxGraphImpl::AddTransaction(Ref& arg, const FeePerWeight& feerate) noexcept { Assume(m_main_chunkindex_observers == 0 || GetTopLevel() != 0); Assume(feerate.size > 0); - // Construct a new Ref. - Ref ret; + Assume(GetRefGraph(arg) == nullptr); // Construct a new Entry, and link it with the Ref. auto idx = m_entries.size(); m_entries.emplace_back(); auto& entry = m_entries.back(); entry.m_main_chunkindex_iterator = m_main_chunkindex.end(); - entry.m_ref = &ret; - GetRefGraph(ret) = this; - GetRefIndex(ret) = idx; + entry.m_ref = &arg; + GetRefGraph(arg) = this; + GetRefIndex(arg) = idx; // Construct a new singleton Cluster (which is necessarily optimally linearized). bool oversized = uint64_t(feerate.size) > m_max_cluster_size; auto cluster = CreateEmptyCluster(1); @@ -2146,8 +2145,6 @@ TxGraph::Ref TxGraphImpl::AddTransaction(const FeePerWeight& feerate) noexcept clusterset.m_oversized = true; clusterset.m_group_data = std::nullopt; } - // Return the Ref. - return ret; } void TxGraphImpl::RemoveTransaction(const Ref& arg) noexcept diff --git a/src/txgraph.h b/src/txgraph.h index 0e1f2c79d07..385db0147cc 100644 --- a/src/txgraph.h +++ b/src/txgraph.h @@ -67,12 +67,14 @@ public: /** Virtual destructor, so inheriting is safe. */ virtual ~TxGraph() = default; - /** Construct a new transaction with the specified feerate, and return a Ref to it. + /** Initialize arg (which must be an empty Ref) to refer to a new transaction in this graph + * with the specified feerate. + * * If a staging graph exists, the new transaction is only created there. feerate.size must be - * strictly positive. In all further calls, only Refs created by AddTransaction() are allowed + * strictly positive. In all further calls, only Refs passed to AddTransaction() are allowed * to be passed to this TxGraph object (or empty Ref objects). Ref objects may outlive the - * TxGraph they were created for. */ - [[nodiscard]] virtual Ref AddTransaction(const FeePerWeight& feerate) noexcept = 0; + * TxGraph they were added to. */ + virtual void AddTransaction(Ref& arg, const FeePerWeight& feerate) noexcept = 0; /** Remove the specified transaction. If a staging graph exists, the removal only happens * there. This is a no-op if the transaction was already removed. * @@ -235,8 +237,7 @@ public: /** Index into the Graph's m_entries. Only used if m_graph != nullptr. */ GraphIndex m_index = GraphIndex(-1); public: - /** Construct an empty Ref. Non-empty Refs can only be created using - * TxGraph::AddTransaction. */ + /** Construct an empty Ref. It can be initialized through TxGraph::AddTransaction. */ Ref() noexcept = default; /** Destroy this Ref. If it is not empty, the corresponding transaction is removed (in both * main and staging, if it exists). */ diff --git a/src/txmempool.cpp b/src/txmempool.cpp index 55c332769d4..58262e7f2f9 100644 --- a/src/txmempool.cpp +++ b/src/txmempool.cpp @@ -1000,8 +1000,9 @@ CTxMemPool::ChangeSet::TxHandle CTxMemPool::ChangeSet::StageAddition(const CTran CAmount delta{0}; m_pool->ApplyDelta(tx->GetHash(), delta); - TxGraph::Ref ref(m_pool->m_txgraph->AddTransaction(FeePerWeight(fee, GetSigOpsAdjustedWeight(GetTransactionWeight(*tx), sigops_cost, ::nBytesPerSigOp)))); - auto newit = m_to_add.emplace(std::move(ref), tx, fee, time, entry_height, entry_sequence, spends_coinbase, sigops_cost, lp).first; + FeePerWeight feerate(fee, GetSigOpsAdjustedWeight(GetTransactionWeight(*tx), sigops_cost, ::nBytesPerSigOp)); + auto newit = m_to_add.emplace(tx, fee, time, entry_height, entry_sequence, spends_coinbase, sigops_cost, lp).first; + m_pool->m_txgraph->AddTransaction(const_cast(*newit), feerate); if (delta) { newit->UpdateModifiedFee(delta); m_pool->m_txgraph->SetTransactionFee(*newit, newit->GetModifiedFee()); From 7427c7d0983050543f1fc7863121d8e2bf4b1511 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Sat, 10 Jan 2026 18:07:30 -0500 Subject: [PATCH 02/10] txgraph: update chunk index on Compact (preparation) This makes TxGraphImpl::Compact() invoke Cluster::Updated() on all affected clusters, in case they have internal GraphIndex values stored that may have become outdated with the renumbering of GraphIndex values that Compact() caused. No such GraphIndex values are currently stored, but this will change in a future commit. --- src/txgraph.cpp | 78 ++++++++++++++++++++++++++++++------------------- 1 file changed, 48 insertions(+), 30 deletions(-) diff --git a/src/txgraph.cpp b/src/txgraph.cpp index d9f5900f306..3e3e4a68f80 100644 --- a/src/txgraph.cpp +++ b/src/txgraph.cpp @@ -182,8 +182,11 @@ public: virtual int GetLevel(const TxGraphImpl& graph) const noexcept = 0; /** Only called by TxGraphImpl::SwapIndexes. */ virtual void UpdateMapping(DepGraphIndex cluster_idx, GraphIndex graph_idx) noexcept = 0; - /** Push changes to Cluster and its linearization to the TxGraphImpl Entry objects. */ - virtual void Updated(TxGraphImpl& graph, int level) noexcept = 0; + /** Push changes to Cluster and its linearization to the TxGraphImpl Entry objects. Main chunk + * information is computed if the cluster is acceptable, or when rename is set. Rename is used + * when called from Compact, to recompute after GraphIndexes may have changed; in this case, + * no chunk index objects are removed or created either. */ + virtual void Updated(TxGraphImpl& graph, int level, bool rename) noexcept = 0; /** Create a copy of this Cluster in staging, returning a pointer to it (used by PullIn). */ virtual Cluster* CopyToStaging(TxGraphImpl& graph) const noexcept = 0; /** Get the list of Clusters in main that conflict with this one (which is assumed to be in staging). */ @@ -279,7 +282,7 @@ public: void ExtractTransactions(const std::function& visit1_fn, const std::function& visit2_fn) noexcept final; int GetLevel(const TxGraphImpl& graph) const noexcept final; void UpdateMapping(DepGraphIndex cluster_idx, GraphIndex graph_idx) noexcept final { m_mapping[cluster_idx] = graph_idx; } - void Updated(TxGraphImpl& graph, int level) noexcept final; + void Updated(TxGraphImpl& graph, int level, bool rename) noexcept final; Cluster* CopyToStaging(TxGraphImpl& graph) const noexcept final; void GetConflicts(const TxGraphImpl& graph, std::vector& out) const noexcept final; void MakeStagingTransactionsMissing(TxGraphImpl& graph) noexcept final; @@ -335,7 +338,7 @@ public: void ExtractTransactions(const std::function& visit1_fn, const std::function& visit2_fn) noexcept final; int GetLevel(const TxGraphImpl& graph) const noexcept final; void UpdateMapping(DepGraphIndex cluster_idx, GraphIndex graph_idx) noexcept final { Assume(cluster_idx == 0); m_graph_index = graph_idx; } - void Updated(TxGraphImpl& graph, int level) noexcept final; + void Updated(TxGraphImpl& graph, int level, bool rename) noexcept final; Cluster* CopyToStaging(TxGraphImpl& graph) const noexcept final; void GetConflicts(const TxGraphImpl& graph, std::vector& out) const noexcept final; void MakeStagingTransactionsMissing(TxGraphImpl& graph) noexcept final; @@ -621,8 +624,9 @@ public: // Simple helper functions. - /** Swap the Entry referred to by a and the one referred to by b. */ - void SwapIndexes(GraphIndex a, GraphIndex b) noexcept; + /** Swap the Entry referred to by a and the one referred to by b. Gather main clusters to + * update afterwards. */ + void SwapIndexes(GraphIndex a, GraphIndex b, std::vector& affected_main) noexcept; /** If idx exists in the specified level ClusterSet (explicitly, or in the level below and not * removed), return the Cluster it is in. Otherwise, return nullptr. */ Cluster* FindCluster(GraphIndex idx, int level) const noexcept { return FindClusterAndLevel(idx, level).first; } @@ -1007,14 +1011,14 @@ void TxGraphImpl::ClearLocator(int level, GraphIndex idx, bool oversized_tx) noe if (level == 0) ClearChunkData(entry); } -void GenericClusterImpl::Updated(TxGraphImpl& graph, int level) noexcept +void GenericClusterImpl::Updated(TxGraphImpl& graph, int level, bool rename) noexcept { // Update all the Locators for this Cluster's Entry objects. for (DepGraphIndex idx : m_linearization) { auto& entry = graph.m_entries[m_mapping[idx]]; // Discard any potential ChunkData prior to modifying the Cluster (as that could // invalidate its ordering). - if (level == 0) graph.ClearChunkData(entry); + if (level == 0 && !rename) graph.ClearChunkData(entry); entry.m_locator[level].SetPresent(this, idx); } // If this is for the main graph (level = 0), and the Cluster's quality is ACCEPTABLE or @@ -1022,7 +1026,10 @@ void GenericClusterImpl::Updated(TxGraphImpl& graph, int level) noexcept // and m_main_chunk_feerate. These fields are only accessed after making the entire graph // ACCEPTABLE, so it is pointless to compute these if we haven't reached that quality level // yet. - if (level == 0 && IsAcceptable()) { + // When rename=true, this is always performed for level 0, to make sure the values inside the + // entries remain consistent with the chunk index (otherwise unrelated chunk index operations + // could cause the index to become corrupted, by inserting elements in the wrong place). + if (level == 0 && (rename || IsAcceptable())) { auto chunking = ChunkLinearizationInfo(m_depgraph, m_linearization); LinearizationIndex lin_idx{0}; // Iterate over the chunks. @@ -1047,7 +1054,7 @@ void GenericClusterImpl::Updated(TxGraphImpl& graph, int level) noexcept // clusters), store the special value -1 as chunk count. chunk_count = LinearizationIndex(-1); } - graph.CreateChunkData(graph_idx, chunk_count); + if (!rename) graph.CreateChunkData(graph_idx, chunk_count); break; } } @@ -1055,7 +1062,7 @@ void GenericClusterImpl::Updated(TxGraphImpl& graph, int level) noexcept } } -void SingletonClusterImpl::Updated(TxGraphImpl& graph, int level) noexcept +void SingletonClusterImpl::Updated(TxGraphImpl& graph, int level, bool rename) noexcept { // Don't do anything if this is empty. if (GetTxCount() == 0) return; @@ -1063,16 +1070,16 @@ void SingletonClusterImpl::Updated(TxGraphImpl& graph, int level) noexcept auto& entry = graph.m_entries[m_graph_index]; // Discard any potential ChunkData prior to modifying the Cluster (as that could // invalidate its ordering). - if (level == 0) graph.ClearChunkData(entry); + if (level == 0 && !rename) graph.ClearChunkData(entry); entry.m_locator[level].SetPresent(this, 0); // If this is for the main graph (level = 0), compute its chunking and store its information in // the Entry's m_main_lin_index and m_main_chunk_feerate. - if (level == 0 && IsAcceptable()) { + if (level == 0 && (rename || IsAcceptable())) { entry.m_main_lin_index = 0; entry.m_main_chunk_feerate = m_feerate; // Always use the special LinearizationIndex(-1), indicating singleton chunk at end of // Cluster, here. - graph.CreateChunkData(m_graph_index, LinearizationIndex(-1)); + if (!rename) graph.CreateChunkData(m_graph_index, LinearizationIndex(-1)); } } @@ -1138,7 +1145,7 @@ Cluster* GenericClusterImpl::CopyToStaging(TxGraphImpl& graph) const noexcept // Insert the new Cluster into the graph. graph.InsertCluster(/*level=*/1, std::move(ret), m_quality); // Update its Locators. - ptr->Updated(graph, /*level=*/1); + ptr->Updated(graph, /*level=*/1, /*rename=*/false); // Update memory usage. graph.GetClusterSet(/*level=*/1).m_cluster_usage += ptr->TotalMemoryUsage(); return ptr; @@ -1155,7 +1162,7 @@ Cluster* SingletonClusterImpl::CopyToStaging(TxGraphImpl& graph) const noexcept // Insert the new Cluster into the graph. graph.InsertCluster(/*level=*/1, std::move(ret), m_quality); // Update its Locators. - ptr->Updated(graph, /*level=*/1); + ptr->Updated(graph, /*level=*/1, /*rename=*/false); // Update memory usage. graph.GetClusterSet(/*level=*/1).m_cluster_usage += ptr->TotalMemoryUsage(); return ptr; @@ -1204,7 +1211,7 @@ void GenericClusterImpl::ApplyRemovals(TxGraphImpl& graph, int level, std::span< graph.GetClusterSet(level).m_cluster_usage += TotalMemoryUsage(); auto new_quality = IsTopological() ? QualityLevel::NEEDS_SPLIT : QualityLevel::NEEDS_SPLIT_FIX; graph.SetClusterQuality(level, m_quality, m_setindex, new_quality); - Updated(graph, level); + Updated(graph, /*level=*/level, /*rename=*/false); } void SingletonClusterImpl::ApplyRemovals(TxGraphImpl& graph, int level, std::span& to_remove) noexcept @@ -1260,7 +1267,7 @@ void GenericClusterImpl::MoveToMain(TxGraphImpl& graph) noexcept // Remove cluster itself from staging and add it to main. auto cluster = graph.ExtractCluster(1, quality, m_setindex); graph.InsertCluster(/*level=*/0, std::move(cluster), quality); - Updated(graph, /*level=*/0); + Updated(graph, /*level=*/0, /*rename=*/false); } void SingletonClusterImpl::MoveToMain(TxGraphImpl& graph) noexcept @@ -1274,7 +1281,7 @@ void SingletonClusterImpl::MoveToMain(TxGraphImpl& graph) noexcept auto cluster = graph.ExtractCluster(/*level=*/1, quality, m_setindex); graph.InsertCluster(/*level=*/0, std::move(cluster), quality); graph.GetClusterSet(/*level=*/0).m_cluster_usage += TotalMemoryUsage(); - Updated(graph, /*level=*/0); + Updated(graph, /*level=*/0, /*rename=*/false); } void GenericClusterImpl::Compact() noexcept @@ -1372,7 +1379,7 @@ bool GenericClusterImpl::Split(TxGraphImpl& graph, int level) noexcept graph.SetClusterQuality(level, m_quality, m_setindex, split_quality); // If this made the quality ACCEPTABLE or OPTIMAL, we need to compute and cache its // chunking. - Updated(graph, level); + Updated(graph, /*level=*/level, /*rename=*/false); return false; } first = false; @@ -1407,7 +1414,7 @@ bool GenericClusterImpl::Split(TxGraphImpl& graph, int level) noexcept } // Update all the Locators of moved transactions, and memory usage. for (Cluster* new_cluster : new_clusters) { - new_cluster->Updated(graph, level); + new_cluster->Updated(graph, /*level=*/level, /*rename=*/false); new_cluster->Compact(); graph.GetClusterSet(level).m_cluster_usage += new_cluster->TotalMemoryUsage(); } @@ -1497,7 +1504,7 @@ void GenericClusterImpl::ApplyDependencies(TxGraphImpl& graph, int level, std::s graph.SetClusterQuality(level, m_quality, m_setindex, QualityLevel::NEEDS_FIX); // Finally push the changes to graph.m_entries. - Updated(graph, level); + Updated(graph, /*level=*/level, /*rename=*/false); } void SingletonClusterImpl::ApplyDependencies(TxGraphImpl&, int, std::span>) noexcept @@ -1653,7 +1660,7 @@ void TxGraphImpl::ApplyRemovals(int up_to_level) noexcept Compact(); } -void TxGraphImpl::SwapIndexes(GraphIndex a, GraphIndex b) noexcept +void TxGraphImpl::SwapIndexes(GraphIndex a, GraphIndex b, std::vector& affected_main) noexcept { Assume(a < m_entries.size()); Assume(b < m_entries.size()); @@ -1669,12 +1676,12 @@ void TxGraphImpl::SwapIndexes(GraphIndex a, GraphIndex b) noexcept if (entry.m_main_chunkindex_iterator != m_main_chunkindex.end()) { entry.m_main_chunkindex_iterator->m_graph_index = idx; } - // Update the locators for both levels. The rest of the Entry information will not change, - // so no need to invoke Cluster::Updated(). + // Update the locators for both levels. for (int level = 0; level < MAX_LEVELS; ++level) { Locator& locator = entry.m_locator[level]; if (locator.IsPresent()) { locator.cluster->UpdateMapping(locator.index, idx); + if (level == 0) affected_main.push_back(locator.cluster); } } } @@ -1702,6 +1709,7 @@ void TxGraphImpl::Compact() noexcept // invalidate them). std::sort(m_unlinked.begin(), m_unlinked.end(), std::greater{}); + std::vector affected_main; auto last = GraphIndex(-1); for (GraphIndex idx : m_unlinked) { // m_unlinked should never contain the same GraphIndex twice (the code below would fail @@ -1718,10 +1726,20 @@ void TxGraphImpl::Compact() noexcept } // Move the entry to the end. - if (idx != m_entries.size() - 1) SwapIndexes(idx, m_entries.size() - 1); + if (idx != m_entries.size() - 1) SwapIndexes(idx, m_entries.size() - 1, affected_main); // Drop the entry for idx, now that it is at the end. m_entries.pop_back(); } + + // In a future commit, chunk information will end up containing a GraphIndex of the + // max-fallback transaction in the chunk. Since GraphIndex values may have been reassigned, we + // will need to recompute the chunk information (even if not IsAcceptable), so that the index + // order and comparisons remain consistent. + std::sort(affected_main.begin(), affected_main.end()); + affected_main.erase(std::unique(affected_main.begin(), affected_main.end()), affected_main.end()); + for (Cluster* cluster : affected_main) { + cluster->Updated(*this, /*level=*/0, /*rename=*/true); + } m_unlinked.clear(); } @@ -2080,7 +2098,7 @@ std::pair GenericClusterImpl::Relinearize(TxGraphImpl& graph, in improved = true; } // Update the Entry objects. - Updated(graph, level); + Updated(graph, /*level=*/level, /*rename=*/false); return {cost, improved}; } @@ -2136,7 +2154,7 @@ void TxGraphImpl::AddTransaction(Ref& arg, const FeePerWeight& feerate) noexcept int level = GetTopLevel(); auto& clusterset = GetClusterSet(level); InsertCluster(level, std::move(cluster), oversized ? QualityLevel::OVERSIZED_SINGLETON : QualityLevel::OPTIMAL); - cluster_ptr->Updated(*this, level); + cluster_ptr->Updated(*this, /*level=*/level, /*rename=*/false); clusterset.m_cluster_usage += cluster_ptr->TotalMemoryUsage(); ++clusterset.m_txcount; // Deal with individually oversized transactions. @@ -2616,7 +2634,7 @@ void GenericClusterImpl::SetFee(TxGraphImpl& graph, int level, DepGraphIndex idx } else if (IsAcceptable()) { graph.SetClusterQuality(level, m_quality, m_setindex, QualityLevel::NEEDS_RELINEARIZE); } - Updated(graph, level); + Updated(graph, /*level=*/level, /*rename=*/false); } void SingletonClusterImpl::SetFee(TxGraphImpl& graph, int level, DepGraphIndex idx, int64_t fee) noexcept @@ -2624,7 +2642,7 @@ void SingletonClusterImpl::SetFee(TxGraphImpl& graph, int level, DepGraphIndex i Assume(GetTxCount()); Assume(idx == 0); m_feerate.fee = fee; - Updated(graph, level); + Updated(graph, /*level=*/level, /*rename=*/false); } void TxGraphImpl::SetTransactionFee(const Ref& ref, int64_t fee) noexcept From 6c1bcb2c7c1a0017562e99195d74c3a05444633b Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Sat, 10 Jan 2026 18:42:50 -0500 Subject: [PATCH 03/10] txgraph: clear cluster's chunk index in ~Ref (preparation) Whenever a TxGraph::Ref is destroyed, if it by then still appears inside main-level clusters, wipe the chunk index entries for those clusters, to prevent having lingering indexes for transactions without Ref. This is preparation for enabling a callback being passed to MakeTxGraph to define a fallback order on objects. Once the Ref for a transaction is gone, it is not possible to invoke the callback anymore. To prevent the index becoming inconsistent, we need to immediately get rid of the index entries when the Ref disappears. This is not a problem, because such destructions necessarily will trigger a relinearization of the cluster (assuming there are transactions in it left) before becoming acceptable again, and the chunk ordering is not observable (through CompareMainOrder, or through the BlockBuilder interface) until that point. However, the index itself needs to remain consistent in the mean time, even if not meaningful. --- src/txgraph.cpp | 50 ++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 39 insertions(+), 11 deletions(-) diff --git a/src/txgraph.cpp b/src/txgraph.cpp index 3e3e4a68f80..ac07579e513 100644 --- a/src/txgraph.cpp +++ b/src/txgraph.cpp @@ -187,6 +187,8 @@ public: * when called from Compact, to recompute after GraphIndexes may have changed; in this case, * no chunk index objects are removed or created either. */ virtual void Updated(TxGraphImpl& graph, int level, bool rename) noexcept = 0; + /** Remove all chunk index entries for this cluster (level=0 only). */ + virtual void RemoveChunkData(TxGraphImpl& graph) noexcept = 0; /** Create a copy of this Cluster in staging, returning a pointer to it (used by PullIn). */ virtual Cluster* CopyToStaging(TxGraphImpl& graph) const noexcept = 0; /** Get the list of Clusters in main that conflict with this one (which is assumed to be in staging). */ @@ -283,6 +285,7 @@ public: int GetLevel(const TxGraphImpl& graph) const noexcept final; void UpdateMapping(DepGraphIndex cluster_idx, GraphIndex graph_idx) noexcept final { m_mapping[cluster_idx] = graph_idx; } void Updated(TxGraphImpl& graph, int level, bool rename) noexcept final; + void RemoveChunkData(TxGraphImpl& graph) noexcept final; Cluster* CopyToStaging(TxGraphImpl& graph) const noexcept final; void GetConflicts(const TxGraphImpl& graph, std::vector& out) const noexcept final; void MakeStagingTransactionsMissing(TxGraphImpl& graph) noexcept final; @@ -339,6 +342,7 @@ public: int GetLevel(const TxGraphImpl& graph) const noexcept final; void UpdateMapping(DepGraphIndex cluster_idx, GraphIndex graph_idx) noexcept final { Assume(cluster_idx == 0); m_graph_index = graph_idx; } void Updated(TxGraphImpl& graph, int level, bool rename) noexcept final; + void RemoveChunkData(TxGraphImpl& graph) noexcept final; Cluster* CopyToStaging(TxGraphImpl& graph) const noexcept final; void GetConflicts(const TxGraphImpl& graph, std::vector& out) const noexcept final; void MakeStagingTransactionsMissing(TxGraphImpl& graph) noexcept final; @@ -697,6 +701,11 @@ public: auto& entry = m_entries[idx]; Assume(entry.m_ref != nullptr); Assume(m_main_chunkindex_observers == 0 || !entry.m_locator[0].IsPresent()); + // Remove all chunk index entries for the affected cluster, to avoid any chunk indexes + // referencing unlinked/destroyed Refs. + if (entry.m_locator[0].IsPresent()) { + entry.m_locator[0].cluster->RemoveChunkData(*this); + } entry.m_ref = nullptr; // Mark the transaction as to be removed in all levels where it explicitly or implicitly // exists. @@ -1011,6 +1020,21 @@ void TxGraphImpl::ClearLocator(int level, GraphIndex idx, bool oversized_tx) noe if (level == 0) ClearChunkData(entry); } +void GenericClusterImpl::RemoveChunkData(TxGraphImpl& graph) noexcept +{ + for (DepGraphIndex idx : m_linearization) { + auto& entry = graph.m_entries[m_mapping[idx]]; + graph.ClearChunkData(entry); + } +} + +void SingletonClusterImpl::RemoveChunkData(TxGraphImpl& graph) noexcept +{ + if (GetTxCount() == 0) return; + auto& entry = graph.m_entries[m_graph_index]; + graph.ClearChunkData(entry); +} + void GenericClusterImpl::Updated(TxGraphImpl& graph, int level, bool rename) noexcept { // Update all the Locators for this Cluster's Entry objects. @@ -2777,14 +2801,16 @@ void GenericClusterImpl::SanityCheck(const TxGraphImpl& graph, int level) const assert(entry.m_main_chunk_feerate == linchunking[chunk_num].feerate); // Verify that an entry in the chunk index exists for every chunk-ending transaction. ++chunk_pos; - bool is_chunk_end = (chunk_pos == linchunking[chunk_num].transactions.Count()); - assert((entry.m_main_chunkindex_iterator != graph.m_main_chunkindex.end()) == is_chunk_end); - if (is_chunk_end) { - auto& chunk_data = *entry.m_main_chunkindex_iterator; - if (m_done == m_depgraph.Positions() && chunk_pos == 1) { - assert(chunk_data.m_chunk_count == LinearizationIndex(-1)); - } else { - assert(chunk_data.m_chunk_count == chunk_pos); + if (graph.m_main_clusterset.m_to_remove.empty()) { + bool is_chunk_end = (chunk_pos == linchunking[chunk_num].transactions.Count()); + assert((entry.m_main_chunkindex_iterator != graph.m_main_chunkindex.end()) == is_chunk_end); + if (is_chunk_end) { + auto& chunk_data = *entry.m_main_chunkindex_iterator; + if (m_done == m_depgraph.Positions() && chunk_pos == 1) { + assert(chunk_data.m_chunk_count == LinearizationIndex(-1)); + } else { + assert(chunk_data.m_chunk_count == chunk_pos); + } } } // If this Cluster has an acceptable quality level, its chunks must be connected. @@ -2808,9 +2834,11 @@ void SingletonClusterImpl::SanityCheck(const TxGraphImpl& graph, int level) cons if (level == 0 && IsAcceptable()) { assert(entry.m_main_lin_index == 0); assert(entry.m_main_chunk_feerate == m_feerate); - assert(entry.m_main_chunkindex_iterator != graph.m_main_chunkindex.end()); - auto& chunk_data = *entry.m_main_chunkindex_iterator; - assert(chunk_data.m_chunk_count == LinearizationIndex(-1)); + if (graph.m_main_clusterset.m_to_remove.empty()) { + assert(entry.m_main_chunkindex_iterator != graph.m_main_chunkindex.end()); + auto& chunk_data = *entry.m_main_chunkindex_iterator; + assert(chunk_data.m_chunk_count == LinearizationIndex(-1)); + } } } } From e0bc73ba9270b860d81e479a7bddcff8cfd8bfb6 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Wed, 7 Jan 2026 10:36:03 -0500 Subject: [PATCH 04/10] clusterlin: sort tx in chunk by feerate and size (feature) This changes the order of transactions within a chunk to be: 1. Topology (parents before children) 2. Individual transaction feerate (high to low) 3. Individual transaction weight (small to large) 4. Random tiebreak (will be changed in a future commit) To do so, use a heap of topology-ready transactions within GetLinearization(), sorted by (2), (3), and (4). This is analogous to the order of chunks within a cluster, which is unchanged: 1. Topology (chunks after chunks they depend on) 2. Chunk feerate (high to low) 3. Chunk weight (small to large) 4. Random tiebreak (will be changed in a future commit) --- src/cluster_linearize.h | 71 +++++++++++++++++++---------- src/test/fuzz/cluster_linearize.cpp | 51 +++++++++++++++++++++ 2 files changed, 99 insertions(+), 23 deletions(-) diff --git a/src/cluster_linearize.h b/src/cluster_linearize.h index 8be16625afc..54d996529af 100644 --- a/src/cluster_linearize.h +++ b/src/cluster_linearize.h @@ -12,6 +12,7 @@ #include #include +#include #include #include #include @@ -687,6 +688,9 @@ private: /** The number of updated transactions in activations/deactivations. */ uint64_t m_cost{0}; + /** The DepGraph we are trying to linearize. */ + const DepGraph& m_depgraph; + /** Pick a random transaction within a set (which must be non-empty). */ TxIdx PickRandomTx(const SetType& tx_idxs) noexcept { @@ -959,7 +963,8 @@ private: public: /** Construct a spanning forest for the given DepGraph, with every transaction in its own chunk * (not topological). */ - explicit SpanningForestState(const DepGraph& depgraph, uint64_t rng_seed) noexcept : m_rng(rng_seed) + explicit SpanningForestState(const DepGraph& depgraph LIFETIMEBOUND, uint64_t rng_seed) noexcept : + m_rng(rng_seed), m_depgraph(depgraph) { m_transaction_idxs = depgraph.Positions(); auto num_transactions = m_transaction_idxs.Count(); @@ -1242,7 +1247,7 @@ public: std::vector ret; ret.reserve(m_transaction_idxs.Count()); /** A heap with all chunks (by representative) that can currently be included, sorted by - * chunk feerate and a random tie-breaker. */ + * chunk feerate (high to low), chunk size (small to large), and a random tie-breaker. */ std::vector> ready_chunks; /** Information about chunks: * - The first value is only used for chunk representatives, and counts the number of @@ -1253,8 +1258,9 @@ public: std::vector> chunk_deps(m_tx_data.size(), {0, 0}); /** The set of all chunk representatives. */ SetType chunk_reps; - /** A list with all transactions within the current chunk that can be included. */ - std::vector ready_tx; + /** A heap with all transactions within the current chunk that can be included, sorted by + * tx feerate (high to low), tx size (small to large), and a random tie-breaker. */ + std::vector> ready_tx; // Populate chunk_deps[c] with the number of {out-of-chunk dependencies, dependencies} the // child has. for (TxIdx chl_idx : m_transaction_idxs) { @@ -1267,16 +1273,35 @@ public: chunk_deps[chl_chunk_rep].first += (par_chunk_rep != chl_chunk_rep); } } + /** Comparison function for the transaction heap. Note that it is a max-heap, so + * tx_cmp_fn(a, b) == true means "a appears after b in the linearization". */ + auto tx_cmp_fn = [&](const auto& a, const auto& b) noexcept { + // First sort by increasing transaction feerate. + auto& a_feerate = m_depgraph.FeeRate(a.first); + auto& b_feerate = m_depgraph.FeeRate(b.first); + auto feerate_cmp = FeeRateCompare(a_feerate, b_feerate); + if (feerate_cmp != 0) return feerate_cmp < 0; + // Then by decreasing transaction size. + if (a_feerate.size != b_feerate.size) { + return a_feerate.size > b_feerate.size; + } + // Tie-break randomly. + if (a.second != b.second) return a.second < b.second; + // Lastly, tie-break by TxIdx. + return a.first < b.first; + }; // Construct a heap with all chunks that have no out-of-chunk dependencies. - /** Comparison function for the heap. */ + /** Comparison function for the chunk heap. Note that it is a max-heap, so + * chunk_cmp_fn(a, b) == true means "a appears after b in the linearization". */ auto chunk_cmp_fn = [&](const std::pair& a, const std::pair& b) noexcept { - auto& chunk_a = m_tx_data[a.first]; - auto& chunk_b = m_tx_data[b.first]; - Assume(chunk_a.chunk_rep == a.first); - Assume(chunk_b.chunk_rep == b.first); - // First sort by chunk feerate. - if (chunk_a.chunk_setinfo.feerate != chunk_b.chunk_setinfo.feerate) { - return chunk_a.chunk_setinfo.feerate < chunk_b.chunk_setinfo.feerate; + // First sort by increasing chunk feerate. + auto& chunk_feerate_a = m_tx_data[a.first].chunk_setinfo.feerate; + auto& chunk_feerate_b = m_tx_data[b.first].chunk_setinfo.feerate; + auto feerate_cmp = FeeRateCompare(chunk_feerate_a, chunk_feerate_b); + if (feerate_cmp != 0) return feerate_cmp < 0; + // Then by decreasing chunk size. + if (chunk_feerate_a.size != chunk_feerate_b.size) { + return chunk_feerate_a.size > chunk_feerate_b.size; } // Tie-break randomly. if (a.second != b.second) return a.second < b.second; @@ -1287,7 +1312,7 @@ public: if (chunk_deps[chunk_rep].first == 0) ready_chunks.emplace_back(chunk_rep, m_rng.rand64()); } std::make_heap(ready_chunks.begin(), ready_chunks.end(), chunk_cmp_fn); - // Pop chunks off the heap, highest-feerate ones first. + // Pop chunks off the heap. while (!ready_chunks.empty()) { auto [chunk_rep, _rnd] = ready_chunks.front(); std::pop_heap(ready_chunks.begin(), ready_chunks.end(), chunk_cmp_fn); @@ -1296,21 +1321,20 @@ public: Assume(chunk_deps[chunk_rep].first == 0); const auto& chunk_txn = m_tx_data[chunk_rep].chunk_setinfo.transactions; // Build heap of all includable transactions in chunk. + Assume(ready_tx.empty()); for (TxIdx tx_idx : chunk_txn) { if (chunk_deps[tx_idx].second == 0) { - ready_tx.push_back(tx_idx); + ready_tx.emplace_back(tx_idx, m_rng.rand64()); } } Assume(!ready_tx.empty()); - // Pick transactions from the ready queue, append them to linearization, and decrement + std::make_heap(ready_tx.begin(), ready_tx.end(), tx_cmp_fn); + // Pick transactions from the ready heap, append them to linearization, and decrement // dependency counts. while (!ready_tx.empty()) { - // Move a random queue element to the back. - auto pos = m_rng.randrange(ready_tx.size()); - if (pos != ready_tx.size() - 1) std::swap(ready_tx.back(), ready_tx[pos]); - // Pop from the back. - auto tx_idx = ready_tx.back(); - Assume(chunk_txn[tx_idx]); + // Pop an element from the tx_ready heap. + auto [tx_idx, _rnd] = ready_tx.front(); + std::pop_heap(ready_tx.begin(), ready_tx.end(), tx_cmp_fn); ready_tx.pop_back(); // Append to linearization. ret.push_back(tx_idx); @@ -1321,8 +1345,9 @@ public: // Decrement tx dependency count. Assume(chunk_deps[chl_idx].second > 0); if (--chunk_deps[chl_idx].second == 0 && chunk_txn[chl_idx]) { - // Child tx has no dependencies left, and is in this chunk. Add it to the tx queue. - ready_tx.push_back(chl_idx); + // Child tx has no dependencies left, and is in this chunk. Add it to the tx heap. + ready_tx.emplace_back(chl_idx, m_rng.rand64()); + std::push_heap(ready_tx.begin(), ready_tx.end(), tx_cmp_fn); } // Decrement chunk dependency count if this is out-of-chunk dependency. if (chl_data.chunk_rep != chunk_rep) { diff --git a/src/test/fuzz/cluster_linearize.cpp b/src/test/fuzz/cluster_linearize.cpp index 6e7e73e1649..be23ef3f2e8 100644 --- a/src/test/fuzz/cluster_linearize.cpp +++ b/src/test/fuzz/cluster_linearize.cpp @@ -1082,6 +1082,57 @@ FUZZ_TARGET(clusterlin_linearize) auto read_chunking = ChunkLinearization(depgraph, read); auto cmp_read = CompareChunks(chunking, read_chunking); assert(cmp_read >= 0); + + // Verify that within every chunk, the transactions are in a valid order. For any pair of + // transactions, it should not be possible to swap them; either due to a missing + // dependency, or because the order would be inconsistent with decreasing feerate and + // increasing size. + auto chunking_info = ChunkLinearizationInfo(depgraph, linearization); + /** The set of all transactions (strictly) before tx1 (see below), or (strictly) before + * chunk1 (see even further below). */ + TestBitSet done; + unsigned pos{0}; + for (const auto& chunk : chunking_info) { + auto chunk_start = pos; + auto chunk_end = pos + chunk.transactions.Count() - 1; + // Go over all pairs of transactions. done is the set of transactions seen before pos1. + for (unsigned pos1 = chunk_start; pos1 <= chunk_end; ++pos1) { + auto tx1 = linearization[pos1]; + for (unsigned pos2 = pos1 + 1; pos2 <= chunk_end; ++pos2) { + auto tx2 = linearization[pos2]; + // Check whether tx2 only depends on transactions that precede tx1. + if ((depgraph.Ancestors(tx2) - done).Count() == 1) { + // tx2 could take position pos1. + // Verify that individual transaction feerate is decreasing (note that >= + // tie-breaks by size). + assert(depgraph.FeeRate(tx1) >= depgraph.FeeRate(tx2)); + } + } + done.Set(tx1); + } + pos += chunk.transactions.Count(); + } + + // Verify that chunks themselves are in a valid order. For any pair of chunks, it should + // not be possible to swap them; either due to a missing dependency, or because the order + // would be inconsistent with decreasing chunk feerate and increasing chunk size. + done = {}; + // Go over all pairs of chunks. done is the set of transactions seen before chunk_num1. + for (unsigned chunk_num1 = 0; chunk_num1 < chunking_info.size(); ++chunk_num1) { + const auto& chunk1 = chunking_info[chunk_num1]; + for (unsigned chunk_num2 = chunk_num1 + 1; chunk_num2 < chunking_info.size(); ++chunk_num2) { + const auto& chunk2 = chunking_info[chunk_num2]; + TestBitSet chunk2_ancestors; + for (auto tx : chunk2.transactions) chunk2_ancestors |= depgraph.Ancestors(tx); + // Check whether chunk2 only depends on transactions that precede chunk1. + if ((chunk2_ancestors - done).IsSubsetOf(chunk2.transactions)) { + // chunk2 could take position chunk_num1. + // Verify that chunk feerate is decreasing (note that >= tie-breaks by size). + assert(chunk1.feerate >= chunk2.feerate); + } + } + done |= chunk1.transactions; + } } } From 8bfbba32077cb8682208ef31748a10562be027db Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Wed, 7 Jan 2026 10:59:24 -0500 Subject: [PATCH 05/10] txgraph: sort distinct-cluster chunks by equal-feerate-prefix size (feature) This makes TxGraph track the equal-feerate-prefix size of all chunks in all clusters in the main graph, and uses it to sort chunks coming from distinct clusters. The order of chunks across clusters becomes: 1. Feerate (high to low) 2. Equal-feerate-prefix (small to large) 3. Cluster sequence number (old to new); this will be changed later. The equal-feerate-prefix size of a chunk C is defined as the sum of the weights of all chunks in the same cluster as C, with the same feerate as C, up to and including C itself, in linearization order (but excluding such chunks that appear after C). This is an approximation of sorting chunks from small to large across clusters, while remaining consistent with intra-cluster linearization order. --- src/test/fuzz/txgraph.cpp | 30 ++++++++++++++++++++++++++ src/txgraph.cpp | 44 +++++++++++++++++++++++++++++++++++++-- 2 files changed, 72 insertions(+), 2 deletions(-) diff --git a/src/test/fuzz/txgraph.cpp b/src/test/fuzz/txgraph.cpp index 6d5ac88218d..49945e65b15 100644 --- a/src/test/fuzz/txgraph.cpp +++ b/src/test/fuzz/txgraph.cpp @@ -1069,6 +1069,36 @@ FUZZ_TARGET(txgraph) auto sim_diagram = ChunkLinearization(sims[0].graph, sim_lin); auto cmp = CompareChunks(real_diagram, sim_diagram); assert(cmp == 0); + + // Verify consistency of cross-cluster chunk ordering with tie-break (equal-feerate + // prefix size). + auto real_chunking = ChunkLinearizationInfo(sims[0].graph, vec1); + /** Map with one entry per component of the sim main graph. Key is the first Pos of the + * component. Value is the sum of all chunk sizes from that component seen + * already, at the current chunk feerate. */ + std::map comp_prefix_sizes; + /** Current chunk feerate. */ + FeeFrac last_chunk_feerate; + /** Largest seen equal-feerate chunk prefix size. */ + int32_t max_chunk_prefix_size{0}; + for (const auto& chunk : real_chunking) { + // If this is the first chunk with a strictly lower feerate, reset. + if (chunk.feerate << last_chunk_feerate) { + comp_prefix_sizes.clear(); + max_chunk_prefix_size = 0; + } + last_chunk_feerate = chunk.feerate; + // Find which sim component this chunk belongs to. + auto component = sims[0].graph.GetConnectedComponent(sims[0].graph.Positions(), chunk.transactions.First()); + assert(chunk.transactions.IsSubsetOf(component)); + auto comp_key = component.First(); + auto& comp_prefix_size = comp_prefix_sizes[comp_key]; + comp_prefix_size += chunk.feerate.size; + // Verify consistency: within each component (= cluster in txgraph), the + // equal-feerate chunk prefix size must be monotonically increasing. + assert(comp_prefix_size >= max_chunk_prefix_size); + max_chunk_prefix_size = comp_prefix_size; + } } // For every transaction in the total ordering, find a random one before it and after it, diff --git a/src/txgraph.cpp b/src/txgraph.cpp index ac07579e513..60c8b1facb8 100644 --- a/src/txgraph.cpp +++ b/src/txgraph.cpp @@ -497,14 +497,22 @@ private: auto feerate_cmp = FeeRateCompare(entry_b.m_main_chunk_feerate, entry_a.m_main_chunk_feerate); if (feerate_cmp < 0) return std::strong_ordering::less; if (feerate_cmp > 0) return std::strong_ordering::greater; - // Compare Cluster m_sequence as tie-break for equal chunk feerates. + // Compare equal-feerate chunk prefix size for comparing equal chunk feerates. This does two + // things: it distinguishes equal-feerate chunks within the same cluster (because later + // ones will always have a higher prefix size), and it may distinguish equal-feerate chunks + // from distinct clusters. + if (entry_a.m_main_equal_feerate_chunk_prefix_size != entry_b.m_main_equal_feerate_chunk_prefix_size) { + return entry_a.m_main_equal_feerate_chunk_prefix_size <=> entry_b.m_main_equal_feerate_chunk_prefix_size; + } + // Compare Cluster m_sequence as tie-break for equal chunk feerates in distinct clusters, + // when the equal-feerate-prefix size is also the same. const auto& locator_a = entry_a.m_locator[0]; const auto& locator_b = entry_b.m_locator[0]; Assume(locator_a.IsPresent() && locator_b.IsPresent()); if (locator_a.cluster != locator_b.cluster) { return CompareClusters(locator_a.cluster, locator_b.cluster); } - // As final tie-break, compare position within cluster linearization. + // Within a single chunk, sort by position within cluster linearization. return entry_a.m_main_lin_index <=> entry_b.m_main_lin_index; } @@ -595,6 +603,13 @@ private: Locator m_locator[MAX_LEVELS]; /** The chunk feerate of this transaction in main (if present in m_locator[0]). */ FeePerWeight m_main_chunk_feerate; + /** The equal-feerate chunk prefix size of this transaction in main. If the transaction is + * part of chunk C in main, then this gives the sum of the sizes of all chunks in C's + * cluster, whose feerate is equal to that of C, which do not appear after C itself in + * the cluster's linearization. + * This provides a way to sort equal-feerate chunks across clusters, in a way that agrees + * with the within-cluster chunk ordering. */ + int32_t m_main_equal_feerate_chunk_prefix_size; /** The position this transaction has in the main linearization (if present). */ LinearizationIndex m_main_lin_index; }; @@ -1056,11 +1071,23 @@ void GenericClusterImpl::Updated(TxGraphImpl& graph, int level, bool rename) noe if (level == 0 && (rename || IsAcceptable())) { auto chunking = ChunkLinearizationInfo(m_depgraph, m_linearization); LinearizationIndex lin_idx{0}; + /** The sum of all chunk feerate FeeFracs with the same feerate as the current chunk, + * up to and including the current chunk. */ + FeeFrac equal_feerate_chunk_feerate; // Iterate over the chunks. for (unsigned chunk_idx = 0; chunk_idx < chunking.size(); ++chunk_idx) { auto& chunk = chunking[chunk_idx]; auto chunk_count = chunk.transactions.Count(); Assume(chunk_count > 0); + // Update equal_feerate_chunk_feerate to include this chunk, starting over when the + // feerate changed. + if (chunk.feerate << equal_feerate_chunk_feerate) { + equal_feerate_chunk_feerate = chunk.feerate; + } else { + // Note that this is adding fees to fees, and sizes to sizes, so the overall + // ratio remains the same; it's just accounting for the size of the added chunk. + equal_feerate_chunk_feerate += chunk.feerate; + } // Iterate over the transactions in the linearization, which must match those in chunk. while (true) { DepGraphIndex idx = m_linearization[lin_idx]; @@ -1068,6 +1095,7 @@ void GenericClusterImpl::Updated(TxGraphImpl& graph, int level, bool rename) noe auto& entry = graph.m_entries[graph_idx]; entry.m_main_lin_index = lin_idx++; entry.m_main_chunk_feerate = FeePerWeight::FromFeeFrac(chunk.feerate); + entry.m_main_equal_feerate_chunk_prefix_size = equal_feerate_chunk_feerate.size; Assume(chunk.transactions[idx]); chunk.transactions.Reset(idx); if (chunk.transactions.None()) { @@ -1101,6 +1129,7 @@ void SingletonClusterImpl::Updated(TxGraphImpl& graph, int level, bool rename) n if (level == 0 && (rename || IsAcceptable())) { entry.m_main_lin_index = 0; entry.m_main_chunk_feerate = m_feerate; + entry.m_main_equal_feerate_chunk_prefix_size = m_feerate.size; // Always use the special LinearizationIndex(-1), indicating singleton chunk at end of // Cluster, here. if (!rename) graph.CreateChunkData(m_graph_index, LinearizationIndex(-1)); @@ -2779,6 +2808,8 @@ void GenericClusterImpl::SanityCheck(const TxGraphImpl& graph, int level) const LinearizationIndex linindex{0}; DepGraphIndex chunk_pos{0}; //!< position within the current chunk assert(m_depgraph.IsAcyclic()); + if (m_linearization.empty()) return; + FeeFrac equal_feerate_prefix = linchunking[chunk_num].feerate; for (auto lin_pos : m_linearization) { assert(lin_pos < m_mapping.size()); const auto& entry = graph.m_entries[m_mapping[lin_pos]]; @@ -2795,10 +2826,18 @@ void GenericClusterImpl::SanityCheck(const TxGraphImpl& graph, int level) const assert(entry.m_main_lin_index == linindex); ++linindex; if (!linchunking[chunk_num].transactions[lin_pos]) { + // First transaction of a new chunk. ++chunk_num; chunk_pos = 0; + if (linchunking[chunk_num].feerate << equal_feerate_prefix) { + equal_feerate_prefix = linchunking[chunk_num].feerate; + } else { + assert(!(linchunking[chunk_num].feerate >> equal_feerate_prefix)); + equal_feerate_prefix += linchunking[chunk_num].feerate; + } } assert(entry.m_main_chunk_feerate == linchunking[chunk_num].feerate); + assert(entry.m_main_equal_feerate_chunk_prefix_size == equal_feerate_prefix.size); // Verify that an entry in the chunk index exists for every chunk-ending transaction. ++chunk_pos; if (graph.m_main_clusterset.m_to_remove.empty()) { @@ -2834,6 +2873,7 @@ void SingletonClusterImpl::SanityCheck(const TxGraphImpl& graph, int level) cons if (level == 0 && IsAcceptable()) { assert(entry.m_main_lin_index == 0); assert(entry.m_main_chunk_feerate == m_feerate); + assert(entry.m_main_equal_feerate_chunk_prefix_size == m_feerate.size); if (graph.m_main_clusterset.m_to_remove.empty()) { assert(entry.m_main_chunkindex_iterator != graph.m_main_chunkindex.end()); auto& chunk_data = *entry.m_main_chunkindex_iterator; From 39d0052cbf478a729ae0288262003bba9c12690b Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Wed, 7 Jan 2026 15:02:02 -0500 Subject: [PATCH 06/10] clusterlin: make optimal linearizations deterministic (feature) This allows passing in a fallback order comparator to Linearize(), which is used as final tiebreak when deciding the order of chunks and transactions within a chunk, rather than a random tiebreak. The order of transactions within a chunk becomes: 1. Topology (parents before children) 2. Individual transaction feerate (high to low) 3. Weight (small to large) 4. Fallback (low to high fallback order) The order of chunks within a cluster becomes: 1. Topology (chunks after their dependencies) 2. Feerate (high to low) 3. Weight (small to large) 4. Max-fallback (chunk with lowest maximum-fallback-tx first) For now, txgraph passes a naive comparator to Linearize(), which makes the cluster order deterministic when treating the input transactions as identified by the DepGraphIndex. However, since DepGraphIndexes are the result of possibly-randomized operations inside txgraph, this doesn't actually make txgraph's per-cluster ordering deterministic. That will be changed in a later commit, by using a txid-based fallback instead. --- src/bench/cluster_linearize.cpp | 6 +- src/cluster_linearize.h | 109 +++++-- src/test/cluster_linearize_tests.cpp | 463 +++++++++++++-------------- src/test/fuzz/cluster_linearize.cpp | 27 +- src/test/fuzz/txgraph.cpp | 23 +- src/txgraph.cpp | 8 +- 6 files changed, 361 insertions(+), 275 deletions(-) diff --git a/src/bench/cluster_linearize.cpp b/src/bench/cluster_linearize.cpp index 88f8bf28350..d345a7cad1d 100644 --- a/src/bench/cluster_linearize.cpp +++ b/src/bench/cluster_linearize.cpp @@ -55,7 +55,7 @@ void BenchLinearizeOptimallyTotal(benchmark::Bench& bench, const std::string& na // Benchmark the total time to optimal. uint64_t rng_seed = 0; bench.name(bench_name).run([&] { - auto [_lin, optimal, _cost] = Linearize(depgraph, /*max_iterations=*/10000000, rng_seed++); + auto [_lin, optimal, _cost] = Linearize(depgraph, /*max_iterations=*/10000000, rng_seed++, IndexTxOrder{}); assert(optimal); }); } @@ -72,7 +72,7 @@ void BenchLinearizeOptimallyPerCost(benchmark::Bench& bench, const std::string& // Determine the cost of 100 rng_seeds. uint64_t total_cost = 0; for (uint64_t iter = 0; iter < 100; ++iter) { - auto [_lin, optimal, cost] = Linearize(depgraph, /*max_iterations=*/10000000, /*rng_seed=*/iter); + auto [_lin, optimal, cost] = Linearize(depgraph, /*max_iterations=*/10000000, /*rng_seed=*/iter, IndexTxOrder{}); total_cost += cost; } @@ -80,7 +80,7 @@ void BenchLinearizeOptimallyPerCost(benchmark::Bench& bench, const std::string& bench.name(bench_name).unit("cost").batch(total_cost).run([&] { uint64_t recompute_cost = 0; for (uint64_t iter = 0; iter < 100; ++iter) { - auto [_lin, optimal, cost] = Linearize(depgraph, /*max_iterations=*/10000000, /*rng_seed=*/iter); + auto [_lin, optimal, cost] = Linearize(depgraph, /*max_iterations=*/10000000, /*rng_seed=*/iter, IndexTxOrder{}); assert(optimal); recompute_cost += cost; } diff --git a/src/cluster_linearize.h b/src/cluster_linearize.h index 54d996529af..00627d6f167 100644 --- a/src/cluster_linearize.h +++ b/src/cluster_linearize.h @@ -462,6 +462,16 @@ std::vector ChunkLinearization(const DepGraph& depgraph, std:: return ret; } +/** Concept for function objects that return std::strong_ordering when invoked with two Args. */ +template +concept StrongComparator = + std::regular_invocable && + std::is_same_v, std::strong_ordering>; + +/** Simple default transaction ordering function for SpanningForestState::GetLinearization() and + * Linearize(), which just sorts by DepGraphIndex. */ +using IndexTxOrder = std::compare_three_way; + /** Class to represent the internal state of the spanning-forest linearization (SFL) algorithm. * * At all times, each dependency is marked as either "active" or "inactive". The subset of active @@ -636,7 +646,7 @@ private: InsecureRandomContext m_rng; /** Data type to represent indexing into m_tx_data. */ - using TxIdx = uint32_t; + using TxIdx = DepGraphIndex; /** Data type to represent indexing into m_dep_data. */ using DepIdx = uint32_t; @@ -1240,15 +1250,30 @@ public: } /** Construct a topologically-valid linearization from the current forest state. Must be - * topological. */ - std::vector GetLinearization() noexcept + * topological. fallback_order is a comparator that defines a strong order for DepGraphIndexes + * in this cluster, used to order equal-feerate transactions and chunks. + * + * Specifically, the resulting order consists of: + * - The chunks of the current SFL state, sorted by (in decreasing order of priority): + * - topology (parents before children) + * - highest chunk feerate first + * - smallest chunk size first + * - the chunk with the lowest maximum transaction, by fallback_order, first + * - The transactions within a chunk, sorted by (in decreasing order of priority): + * - topology (parents before children) + * - highest tx feerate first + * - smallest tx size first + * - the lowest transaction, by fallback_order, first + */ + std::vector GetLinearization(const StrongComparator auto& fallback_order) const noexcept { /** The output linearization. */ std::vector ret; ret.reserve(m_transaction_idxs.Count()); /** A heap with all chunks (by representative) that can currently be included, sorted by - * chunk feerate (high to low), chunk size (small to large), and a random tie-breaker. */ - std::vector> ready_chunks; + * chunk feerate (high to low), chunk size (small to large), and by least maximum element + * according to the fallback order (which is the second pair element). */ + std::vector> ready_chunks; /** Information about chunks: * - The first value is only used for chunk representatives, and counts the number of * unmet dependencies this chunk has on other chunks (not including dependencies within @@ -1259,8 +1284,8 @@ public: /** The set of all chunk representatives. */ SetType chunk_reps; /** A heap with all transactions within the current chunk that can be included, sorted by - * tx feerate (high to low), tx size (small to large), and a random tie-breaker. */ - std::vector> ready_tx; + * tx feerate (high to low), tx size (small to large), and fallback order. */ + std::vector ready_tx; // Populate chunk_deps[c] with the number of {out-of-chunk dependencies, dependencies} the // child has. for (TxIdx chl_idx : m_transaction_idxs) { @@ -1273,27 +1298,45 @@ public: chunk_deps[chl_chunk_rep].first += (par_chunk_rep != chl_chunk_rep); } } + /** Function to compute the highest element of a chunk, by fallback_order. */ + auto max_fallback_fn = [&](TxIdx chunk_rep) noexcept { + auto& chunk = m_tx_data[chunk_rep].chunk_setinfo.transactions; + auto it = chunk.begin(); + DepGraphIndex ret = *it; + ++it; + while (it != chunk.end()) { + if (fallback_order(*it, ret) > 0) ret = *it; + ++it; + } + return ret; + }; /** Comparison function for the transaction heap. Note that it is a max-heap, so * tx_cmp_fn(a, b) == true means "a appears after b in the linearization". */ auto tx_cmp_fn = [&](const auto& a, const auto& b) noexcept { + // Bail out for identical transactions. + if (a == b) return false; // First sort by increasing transaction feerate. - auto& a_feerate = m_depgraph.FeeRate(a.first); - auto& b_feerate = m_depgraph.FeeRate(b.first); + auto& a_feerate = m_depgraph.FeeRate(a); + auto& b_feerate = m_depgraph.FeeRate(b); auto feerate_cmp = FeeRateCompare(a_feerate, b_feerate); if (feerate_cmp != 0) return feerate_cmp < 0; // Then by decreasing transaction size. if (a_feerate.size != b_feerate.size) { return a_feerate.size > b_feerate.size; } - // Tie-break randomly. - if (a.second != b.second) return a.second < b.second; - // Lastly, tie-break by TxIdx. - return a.first < b.first; + // Tie-break by decreasing fallback_order. + auto fallback_cmp = fallback_order(a, b); + if (fallback_cmp != 0) return fallback_cmp > 0; + // This should not be hit, because fallback_order defines a strong ordering. + Assume(false); + return a < b; }; // Construct a heap with all chunks that have no out-of-chunk dependencies. /** Comparison function for the chunk heap. Note that it is a max-heap, so * chunk_cmp_fn(a, b) == true means "a appears after b in the linearization". */ - auto chunk_cmp_fn = [&](const std::pair& a, const std::pair& b) noexcept { + auto chunk_cmp_fn = [&](const auto& a, const auto& b) noexcept { + // Bail out for identical chunks. + if (a.first == b.first) return false; // First sort by increasing chunk feerate. auto& chunk_feerate_a = m_tx_data[a.first].chunk_setinfo.feerate; auto& chunk_feerate_b = m_tx_data[b.first].chunk_setinfo.feerate; @@ -1303,13 +1346,18 @@ public: if (chunk_feerate_a.size != chunk_feerate_b.size) { return chunk_feerate_a.size > chunk_feerate_b.size; } - // Tie-break randomly. - if (a.second != b.second) return a.second < b.second; - // Lastly, tie-break by chunk representative. - return a.first < b.first; + // Tie-break by decreasing fallback_order. + auto fallback_cmp = fallback_order(a.second, b.second); + if (fallback_cmp != 0) return fallback_cmp > 0; + // This should not be hit, because fallback_order defines a strong ordering. + Assume(false); + return a.second < b.second; }; + // Construct a heap with all chunks that have no out-of-chunk dependencies. for (TxIdx chunk_rep : chunk_reps) { - if (chunk_deps[chunk_rep].first == 0) ready_chunks.emplace_back(chunk_rep, m_rng.rand64()); + if (chunk_deps[chunk_rep].first == 0) { + ready_chunks.emplace_back(chunk_rep, max_fallback_fn(chunk_rep)); + } } std::make_heap(ready_chunks.begin(), ready_chunks.end(), chunk_cmp_fn); // Pop chunks off the heap. @@ -1323,9 +1371,7 @@ public: // Build heap of all includable transactions in chunk. Assume(ready_tx.empty()); for (TxIdx tx_idx : chunk_txn) { - if (chunk_deps[tx_idx].second == 0) { - ready_tx.emplace_back(tx_idx, m_rng.rand64()); - } + if (chunk_deps[tx_idx].second == 0) ready_tx.push_back(tx_idx); } Assume(!ready_tx.empty()); std::make_heap(ready_tx.begin(), ready_tx.end(), tx_cmp_fn); @@ -1333,7 +1379,7 @@ public: // dependency counts. while (!ready_tx.empty()) { // Pop an element from the tx_ready heap. - auto [tx_idx, _rnd] = ready_tx.front(); + auto tx_idx = ready_tx.front(); std::pop_heap(ready_tx.begin(), ready_tx.end(), tx_cmp_fn); ready_tx.pop_back(); // Append to linearization. @@ -1346,7 +1392,7 @@ public: Assume(chunk_deps[chl_idx].second > 0); if (--chunk_deps[chl_idx].second == 0 && chunk_txn[chl_idx]) { // Child tx has no dependencies left, and is in this chunk. Add it to the tx heap. - ready_tx.emplace_back(chl_idx, m_rng.rand64()); + ready_tx.push_back(chl_idx); std::push_heap(ready_tx.begin(), ready_tx.end(), tx_cmp_fn); } // Decrement chunk dependency count if this is out-of-chunk dependency. @@ -1354,7 +1400,7 @@ public: Assume(chunk_deps[chl_data.chunk_rep].first > 0); if (--chunk_deps[chl_data.chunk_rep].first == 0) { // Child chunk has no dependencies left. Add it to the chunk heap. - ready_chunks.emplace_back(chl_data.chunk_rep, m_rng.rand64()); + ready_chunks.emplace_back(chl_data.chunk_rep, max_fallback_fn(chl_data.chunk_rep)); std::push_heap(ready_chunks.begin(), ready_chunks.end(), chunk_cmp_fn); } } @@ -1546,6 +1592,9 @@ public: * @param[in] rng_seed A random number seed to control search order. This prevents peers * from predicting exactly which clusters would be hard for us to * linearize. + * @param[in] fallback_order A comparator to order transactions, used to sort equal-feerate + * chunks and transactions. See SpanningForestState::GetLinearization + * for details. * @param[in] old_linearization An existing linearization for the cluster, or empty. * @param[in] is_topological (Only relevant if old_linearization is not empty) Whether * old_linearization is topologically valid. @@ -1557,7 +1606,13 @@ public: * - How many optimization steps were actually performed. */ template -std::tuple, bool, uint64_t> Linearize(const DepGraph& depgraph, uint64_t max_iterations, uint64_t rng_seed, std::span old_linearization = {}, bool is_topological = true) noexcept +std::tuple, bool, uint64_t> Linearize( + const DepGraph& depgraph, + uint64_t max_iterations, + uint64_t rng_seed, + const StrongComparator auto& fallback_order, + std::span old_linearization = {}, + bool is_topological = true) noexcept { /** Initialize a spanning forest data structure for this cluster. */ SpanningForestState forest(depgraph, rng_seed); @@ -1587,7 +1642,7 @@ std::tuple, bool, uint64_t> Linearize(const DepGraph< } } while (forest.GetCost() < max_iterations); } - return {forest.GetLinearization(), optimal, forest.GetCost()}; + return {forest.GetLinearization(fallback_order), optimal, forest.GetCost()}; } /** Improve a given linearization. diff --git a/src/test/cluster_linearize_tests.cpp b/src/test/cluster_linearize_tests.cpp index 92e80f7cda3..e14b5ebc94a 100644 --- a/src/test/cluster_linearize_tests.cpp +++ b/src/test/cluster_linearize_tests.cpp @@ -54,7 +54,7 @@ void TestDepGraphSerialization(const std::vector>& c BOOST_CHECK(depgraph == depgraph_read); } -void TestOptimalLinearization(const std::vector& enc, const std::vector& optimal_diagram) +void TestOptimalLinearization(std::span enc, std::initializer_list optimal_linearization) { DepGraphIndex tx_count = 0; FastRandomContext rng; @@ -88,14 +88,11 @@ void TestOptimalLinearization(const std::vector& enc, const std::vector is_topological = false; break; } - std::tie(lin, opt, cost) = Linearize(depgraph, 1000000000000, rng.rand64(), lin, is_topological); + std::tie(lin, opt, cost) = Linearize(depgraph, 1000000000000, rng.rand64(), IndexTxOrder{}, lin, is_topological); BOOST_CHECK(opt); BOOST_CHECK(cost <= MaxOptimalLinearizationIters(depgraph.TxCount())); SanityCheck(depgraph, lin); - auto chunking = ChunkLinearization(depgraph, lin); - BOOST_CHECK(std::is_eq(CompareChunks(chunking, optimal_diagram))); - // Verify that the chunks are minimal. - BOOST_CHECK_EQUAL(chunking.size(), optimal_diagram.size()); + BOOST_CHECK(std::ranges::equal(lin, optimal_linearization)); } tx_count = depgraph.PositionRange(); }; @@ -244,239 +241,239 @@ BOOST_AUTO_TEST_CASE(depgraph_optimal_tests) // Compare linearizations with known-optimal chunk feerate diagrams. // Hard clusters (according to various metrics) that appeared in replayed 2023 mempool data, ranging from 2 to 64 transactions. - TestOptimalLinearization("9276fa3a009c3b80cd4001a21680d85c02927bfa5403934280845404a04c80cf0805c75b82c22206a46880f532079c7e80b85608965780916a09a04a80cf080a9823809b3e0bb27b81ec0c0c8540c60e0c0c993e80c86a0d0b8540c2020c0c9352809f780c09972f80f84a080c85449900080c875da164080c875081ae54070c8335af4c071f9c6781a72a13010f99108190160e000e85419f2c07168332903c05158540819e54041216ba5183907a140000001182428d080024a25c83c11201040400010609b6668487240004060000000000"_hex_v_u8, {{47188, 8550}, {42800, 7755}, {325314, 79021}, {2070, 833}, {900, 450}, {2226, 1117}, {1664, 836}, {1118, 562}}); - TestOptimalLinearization("850d81fd4000850e81fd400000850d81fd400000850d81fd400000850e8285000000850d8285000000850e8288600000850e8288600000850e828860000000"_hex_v_u8, {{223440, 7034}}); - TestOptimalLinearization("818f1c8a935a0083219530000083219530010083219530020083219530030083219530040083219530050083219530060083219530070083219530080000"_hex_v_u8, {{104325, 39749}}); - TestOptimalLinearization("836880bf4000834c80b6600000836880bf400100834c80b6600001836880bf400101834c80b6600002836880bf400102834c80b6600003836880bf400103834c80b6600004836880bf400104834c80b6600005836880bf400105836880bf400006834c80b6600106834c80b6600106836880bf400206834c80b6600008836880bf400108836880bf40000900"_hex_v_u8, {{12320, 616}, {11760, 588}, {12320, 616}, {11760, 588}, {12320, 616}, {11760, 588}, {12320, 616}, {11760, 588}, {12320, 616}, {11760, 588}, {12320, 616}, {11760, 588}, {12320, 616}, {11760, 588}, {12320, 616}, {11760, 588}, {12320, 616}, {11760, 588}, {12320, 616}, {12320, 616}}); - TestOptimalLinearization("84a22e8fce380083208c38000083208c38010083208c38020083208c38030083208c38040083208c38050083208c38060083208c38070083208c38080083208c38090000"_hex_v_u8, {{144756, 91886}}); - TestOptimalLinearization("8361a8340084309730000000"_hex_v_u8, {{2650, 609}, {1560, 688}}); - TestOptimalLinearization("829428f0fe20008319809604000183198096040100831980960402008319809604030083198096040400831980960405008319809604060083198096040700831980960408008319809604090083198096040a0083198096040b0083198096040c0083198096040d0083198096040e0083198096040f008319809604100083198096041100831980960412008319809604130083198096041400831980960415008319809604160083198096041700831980960418008319809604190083198096041a0000"_hex_v_u8, {{933840, 51880}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}}); - TestOptimalLinearization("854ec47200854ec4720001854ec4720001854ec4720001854ec4720001854ec4720001854ec4720001854ec4720001854ec4720001854ec4720000854ec4720000854ec4720000854ec4720000854ec4720000854ec4720000854ec4720000854ec4720000854ec4720000854ec4720000854ec4720000854ec4720000854ec4720000854ec4720000854ec4720000854ec472000000"_hex_v_u8, {{4473, 846}, {4473, 846}, {4473, 846}, {4473, 846}, {4473, 846}, {4473, 846}, {4473, 846}, {4473, 846}, {4473, 846}, {4473, 846}, {4473, 846}, {4473, 846}, {4473, 846}, {4473, 846}, {4473, 846}, {4473, 846}, {4473, 846}, {4473, 846}, {4473, 846}, {4473, 846}, {4473, 846}, {4473, 846}, {4473, 846}, {4473, 846}, {4473, 846}}); - TestOptimalLinearization("d1378f927c00e81293cc4001f36095ef5202f20195c33203e93a93817404e76793d0700b80ba72a3e82806fd4697e52207da5d91894608c73d8d98401480990c9d954a0af73292e73a0b8090259bba640c808f689bac760de50692fc1e0eac40888c1a0fbf308bcf481080a3259f980c11c30282fd78128b6f83c2300612932d8ba65e0b09896a88837c010011886281d6380e0000040f953c8594580b000000129e0491c0381300000000148235f72802228653818c08021db40c9180620229833180991c011f854081a95c0020833180bd66002082418097740020953c8784000e00000000000201030d8d7c838d0c04011a874f84842a001600"_hex_v_u8, {{248978, 14346}, {1136423, 78068}, {270282, 20244}, {1423139, 109038}, {903617, 69567}, {106746, 10092}}); - TestOptimalLinearization("836880ba5807845d80df200000836880ba580100845d80df200001836880bd0c0101845d80e2100002836880bf400102845d80e5000003836880bf400103845d80e5000004854e818800010300854e818800000300854e818800000200854e818800000100854e819178000000836880ed1c0000845f819b500017854e818b28001700"_hex_v_u8, {{252408, 12326}, {17172, 846}}); - TestOptimalLinearization("854e829b580088318881580000a37a90ae600000a37a90ae600100a37a90ae600200a37a90ae600300835a819e680303835a819e680403835a819e680503835a819e680603835a819e680703835a819e680803835a819e680903835a819e680a03835a819e680b03835a819e680c03835a819e680d03835a819e680e03835a819e680f03835a819e681003835a819e681103835a819e681203835a819e681303835a819e681403835a819e681503835a819e681603835a819e681703835a819e681803835a819e681903835a819e681a03835a819e681902835a819e681b01835a819e681c01835a819e681c02835a819e681e01835a819e681f01835a819e682001835a819e682002835a819e682102835a819e682301835a819e682302835a819e682501835a819e682502835a819e682602835a819e682801835a819e682802835a819e682a01835a819e682a02835a819e682b02835a819e682d01835a819e682d02835a819e682f01835a819e682f02835a819e683002835a819e68320100"_hex_v_u8, {{100312, 2047}, {584400, 19178}, {381780, 12556}, {363360, 11954}, {142320, 4730}}); - TestOptimalLinearization("83688095520089c17481b5cf780000842d809c700000842d809c700100842d809c700200842d809c700300842d809c700400842d809c700500842d809c700600842d809c700700842d809c700800842d809c700900842d809c700a00842d809c700b00842d809c700c00842d809c700d00842d809c700e00842d809c700f00842d809c701000842d809c701100842d809c701200842d809c701300842d809c701400842d809c701500842d809c701600842d809c701700842d809c701800842d809c701900842d809c701a00842d809c701b00842d809c701c00842d809c701d00842d809c701e00842d809c701f00842d809c702000842d809c702100842d809c702200842d809c702300842d809c702400842d809c702500842d809c702600842d809c702700842d809c702800842d809c702900842d809c702a00842d809c702b00842d809c702c00842d809c702d00842d809c702e00842d809c702f00842d809c703000842d809c703100842d809c703200842d809c70330000"_hex_v_u8, {{9641, 616}, {2544700, 172404}, {10104, 685}, {10104, 685}, {10104, 685}, {10104, 685}, {10104, 685}, {10104, 685}, {10104, 685}, {10104, 685}, {10104, 685}, {10104, 685}, {10104, 685}, {10104, 685}, {10104, 685}, {10104, 685}, {10104, 685}, {10104, 685}, {10104, 685}, {10104, 685}, {10104, 685}, {10104, 685}, {10104, 685}, {10104, 685}, {10104, 685}, {10104, 685}, {10104, 685}, {10104, 685}, {10104, 685}, {10104, 685}, {10104, 685}, {10104, 685}, {10104, 685}, {10104, 685}, {10104, 685}, {10104, 685}, {10104, 685}, {10104, 685}, {10104, 685}, {10104, 685}, {10104, 685}, {10104, 685}, {10104, 685}, {10104, 685}, {10104, 685}, {10104, 685}, {10104, 685}, {10104, 685}, {10104, 685}, {10104, 685}, {10104, 685}, {10104, 685}, {10104, 685}, {10104, 685}}); - TestOptimalLinearization("99469a2e008e638f32018e638f32028e638718038e638718048e638718058e648c44068e659002078e639340088f74873c098e6488380a8d6586340b894784240c894784240d8b56852c0ea71993100f8b6d8538108b56852c118e628b76128e638b76138e638b76148e628b76158e648b7616a06c8f78178e638b76188e628838198e638b761a8e6388381b894784241c9412894c1d8e6690521e9c538e1c05199b10f15017000400189527955a1a0000000000001a9e5d8e70120000000000000117b372993c000300000000000000000000000000001800"_hex_v_u8, {{11835, 11678}, {1129, 2022}, {1751, 3398}, {866, 2020}, {827, 2018}, {827, 2018}, {827, 2019}, {827, 2019}, {827, 2019}, {827, 2019}, {827, 2020}, {3025, 8912}, {604, 2018}, {604, 2019}, {604, 2020}, {974, 3795}, {678, 2706}, {542, 2164}, {412, 1645}, {474, 1893}, {1288, 5145}, {406, 1622}, {406, 1622}, {1084, 4332}, {3724, 14884}}); - TestOptimalLinearization("833583380083368338000083328334000083318334000083328334000083368338000083358338000083328334000000"_hex_v_u8, {{284, 565}, {848, 1689}, {850, 1693}, {282, 562}}); - TestOptimalLinearization("80f96f88ab2a008235839b0600008a4880b31801008604ec3c02008235a97c0300833dab7204008752d502050000"_hex_v_u8, {{140794, 37044}}); - TestOptimalLinearization("f9718def4800823ab01c01833980c238028544848f20038478e07c04887280ef2a05823680a54e068081149ea80a07808714ac995208823680a55c0980b85cbcdc020abb759acf180b8338fe680c82359eac280c0c824280a9620d0c857cf9400e0c823ae5520a0c823590c744090c823584ef14090c847c80a32a0a0c8451808b100b0c824280a9420a0c823580a52c0b0c823586bf2c0c0c857c8186200d0c847882c63a0d0c854081cf060e0c833880b66e0f0c8338808e40100b8368809552110b8241de74130a8242c34c1608894480bc48102a851e818356050e0fad56888c401d00000000198fe81c808fc7501a0000000410933d86e120031300000a00"_hex_v_u8, {{42000, 836}, {255465, 8557}, {21507, 832}, {10670, 438}, {10663, 438}, {588686, 25096}, {389673, 16616}, {418483, 17865}, {400487, 17097}, {12508, 569}, {11767, 568}, {16848, 892}, {24863, 1366}, {83604, 4861}, {9184, 568}, {9641, 616}, {10517, 764}, {6138, 449}, {21950, 1708}, {8968, 721}, {84012, 7176}, {4390, 450}, {1184296, 275612}}); - TestOptimalLinearization("82369e200084459e200186569e200282369e200384459e200488649e200586559e200684459e200788649e200886549e200984449e200a82369e200b9961dc600ca34b81da7800000000000000000000000000008368af4c0000869520c6dd6800008368af3800008368af3801008368af3802008368af3803008368af3804008368af3805008368af3806008368af3807008368af3808008368af3809008368af380a008368af380b008368af380c008368af380d008368af380e008368af380f0000"_hex_v_u8, {{692678, 145712}}); - TestOptimalLinearization("8335862e008335862e00008335862e00008335862e00008335862e00008335862e00008335862e00008335862e00008331862600008335862e00008335862e00008335862e00008335862e00008335862e00008335862e0000833d863a00008335862e00008335862e00008544896a000000"_hex_v_u8, {{471, 565}, {471, 565}, {471, 565}, {471, 565}, {471, 565}, {471, 565}, {471, 565}, {471, 565}, {3293, 3951}, {1419, 1703}, {693, 836}}); - TestOptimalLinearization("836183f20200842b84b82e00008a1089f33e0100842a849a7c00018361838f420101842b83ca680002836282f8280102842983b00c000300"_hex_v_u8, {{40129, 609}, {44631, 683}, {89375, 1424}, {42750, 682}, {33825, 609}, {37620, 683}, {32340, 610}, {35910, 681}}); - TestOptimalLinearization("80fc6c80fd300080e03c80f50e01823aaf3402823aac060380f42080f55e04833d84200580ea0580ea6006833e855a0780ce7c81b724088235898b1c08088474bd2c0908875180a10e0a08857cb0000b088239ad260c088336b8180d0889448e660e08823588db0e0e088242ac5a0c08823588df180d08854588660e088478d670120584498a440f08833dbb1e0f088474ea3810088470d83a1108823588ac7812088242844a13088546886614088545d67e1705823a84181b02875c8c0a1707854088601a058241ae3c1b05823587a67e180887548b7e19088241ae3c21018600d6401b08823a84141c088336854825008755f34a1e088335b6001c2d81d25ca2f16e27001e902d80ea6a250318894ce9202206068336d140034c9969829e282800001d82f57fb48c2e260000040e00"_hex_v_u8, {{3098, 442}, {2883, 442}, {1070885, 209051}, {148942, 39219}, {107942, 30418}, {3136, 892}, {738, 713}, {357, 450}, {332, 442}, {624, 832}, {831, 1108}, {837, 1116}, {1011, 1348}, {627, 837}, {627, 838}, {330, 442}, {420, 566}}); - TestOptimalLinearization("80e67480e6740080d53480d56e0180d04881bd62028f108f1c038335cb7204847ce13e0404824184240504823594990c0604823580d07c07048235a6160804857cdd4009048474f2640904823592ce5c0a04833692700b048540ad300d038608b37c0c04823583e0720d048500a9000e048239841c0f048242b70011038540cc681203833e855a13038470bf7c13048545956a16008600be000d1a8f1880990a17000d8a448a4c1600048544f63c1603018f18f1180c0d0b8600ac40041f00"_hex_v_u8, {{4921, 565}, {221979, 33050}, {185495, 29087}, {4980, 832}, {2507, 437}, {9861, 2072}, {4032, 896}, {2968, 832}, {2912, 896}, {76978, 31757}, {1272, 566}, {1461, 837}, {334, 441}, {338, 449}, {429, 574}, {1038, 2064}, {742, 1476}}); - TestOptimalLinearization("84418c6a0080fe1d86fc00000080b97084ea50000080de1c85fc00010080ed4986b930020080a17b848a70030080d07b85c670040080a86b84a630050080e405869320060080db1185ef50070080d11b85c770080080d00185c310090000"_hex_v_u8, {{593589, 297030}}); - TestOptimalLinearization("856ea51800856da5180000856eab080002856eab080002856dab080002856dab08000000"_hex_v_u8, {{16168, 5265}}); - TestOptimalLinearization("83318c2a00833d8c400183318c1c0283318c1c020283318c1c020283358c28020283318c1e020683318c1c020583318c1c0204833d8c40020a833d8c40020883318c1c020683318c1c020e83318c1c020b8331943e0208833d8c40021283318c1e020e83319a0c020a83358d58011183318c1e031083318d08011383318c1c0113833d8c40011583319a0c011483318c1c01169260809308021583358c280118a84380f9100a021383318c1c011983319430001983319938001983319a1c001883319a0c00188540a71609030683319a0c011983319a0c011283319a0c011283319a0c0113833d9a56011483319b52011483359a26011583359b6c011583319a0c011783319b52011683319a0c011983319b52011783319b52011b83319b520118833d9d6a001983309d18001900"_hex_v_u8, {{88836, 35145}}); - TestOptimalLinearization("80886c99f50c00835df5600000835df5600100835df5600200835df5600300835df5600400835df5600500835df5600600835df5600700835df5600800835df5600900835df5600a00835df5600b00835df5600c00835df5600d00835df5600e00835df5600f00835df5601000835df5601100835df5601200835df5601300835df5601400835df5601500835df5601600835df5601700836880cd78180080895badcb740018835b80c9740018835b80c9740118835b80c9740218835b80c9740318835b80c9740418835b80c9740518835b80c9740618835b80c9740718835b80c9740818835b80c9740918835b80c9740a18835b80c9740b18835b80c9740c18835b80c9740d18835b80c9740e18835b80c9740f18835b80c9741018835b80c974111800"_hex_v_u8, {{849296, 46869}, {7600, 605}, {7600, 605}, {7600, 605}, {7600, 605}, {7600, 605}, {7600, 605}, {7600, 605}, {7600, 605}, {7600, 605}, {7600, 605}, {7600, 605}, {7600, 605}, {7600, 605}, {7600, 605}, {7600, 605}, {7600, 605}, {7600, 605}, {7600, 605}, {7600, 605}, {7600, 605}, {7600, 605}, {7600, 605}, {7600, 605}, {7600, 605}}); - TestOptimalLinearization("8514d518008344be3800008514d51801008344be3800018514d51801018514d51800028344be3801028344be3801028514d51802028344be3800048514d51801048344be3800058514d51801058514d51800068344be3801068344be3801068514d51802068344be3800088514d51801088344be3800098514d51801098514d518000a00"_hex_v_u8, {{5516, 788}, {4060, 580}, {5516, 788}, {4060, 580}, {5516, 788}, {4060, 580}, {5516, 788}, {4060, 580}, {5516, 788}, {4060, 580}, {5516, 788}, {4060, 580}, {5516, 788}, {4060, 580}, {5516, 788}, {4060, 580}, {5516, 788}, {4060, 580}, {5516, 788}, {4060, 580}, {5516, 788}, {5516, 788}}); - TestOptimalLinearization("8442922e009069bd3a0000872d9c1a010083618f5e010183618f5e020183618f5e030183618f5e040183618f5e050183618f5e060183618f5e070183618f5e080183618f5e09019743a36609018442922e0a01835f8610010b835f8610020b835f8610030b835f8610040b835f8610050b835f8610060b835f8610070b835f8610080b835f8610090b835f86100a0b835f86100b0b835f86100c0b8442d82a0c0b8441e332001700"_hex_v_u8, {{16489, 3892}, {13636, 7762}, {7827, 10423}}); - TestOptimalLinearization("9420928e2c008368f11a0000c52488dd700000834acf100000834acf100100834acf100200834acf100300834acf100400834acf100500834acf100600834acf100700834acf100800834acf100900834acf100a00834acf100b00834acf100c00834acf100d00834acf100e00834acf100f00834acf101000834acf101100834acf101200834acf101300834acf10140000"_hex_v_u8, {{156630, 2720}, {7309, 616}, {79800, 8996}, {5128, 586}, {5128, 586}, {5128, 586}, {5128, 586}, {5128, 586}, {5128, 586}, {5128, 586}, {5128, 586}, {5128, 586}, {5128, 586}, {5128, 586}, {5128, 586}, {5128, 586}, {5128, 586}, {5128, 586}, {5128, 586}, {5128, 586}, {5128, 586}, {5128, 586}, {5128, 586}, {5128, 586}}); - TestOptimalLinearization("9d2c83920200856cf66200008570f7280100856bf65202008567f60c03008563f54604008572f74c0500856ef7060600856af6400700856af64008008561f52209008566f57a0a008566f57a0b008575f8000c008571f73a0d008571f73a0e00856df6740f00856df67410008565f56811008561f522120000"_hex_v_u8, {{102774, 11745}, {7569, 865}, {7569, 865}, {7604, 869}, {7674, 877}, {7674, 877}, {7709, 881}, {7709, 881}, {7744, 885}, {7665, 876}, {7700, 880}}); - TestOptimalLinearization("854e80806600854e80806600008368e25000008462f54200008368e50601008463f8340001854e80b25c010000854e80b606000183688089400001846280a3620001854e80c00401000083688095520001846280b21c000100"_hex_v_u8, {{120967, 9647}}); - TestOptimalLinearization("836186101483618872001583608842001584508d74001583618812011500"_hex_v_u8, {{2652, 2546}, {585, 609}}); - TestOptimalLinearization("8ee34aafe24c0083208c1a000083208c1a010083208c1a020083208c1a030083208c1a040083208c1a050083208c1a060083208c1a070083208c1a080083208c1a090083208c1a0a0083208c1a0b0083208c1a0c0083208c1a0d0083208c1a0e0083208c1a0f0083208c1a100083208c1a110083208c1a120083208c1a130083208c1a140083208c1a150083208c1a160083208c1a170083208c1a180083208c1a190083208c1a1a0083208c1a1b0083208c1a1c0083208c1a1d0083208c1a1e0083208c1a1f0083208c1a200083208c1a210083208c1a220083208c1a230083208c1a240083208c1a250083208c1a260083208c1a270083208c1a280083208c1a290083208c1a2a0083208c1a2b0083208c1a2c0083208c1a2d0083208c1a2e0083208c1a2f0083208c1a300083208c1a310083208c1a320083208c1a330083208c1a340083208c1a350083208c1a360083208c1a370083208c1a380083208c1a390083208c1a3a0083208c1a3b0000"_hex_v_u8, {{450290, 291274}}); - TestOptimalLinearization("a34c88ff6400835c80a4140000835c80a4140100835c80a4140200835c80a4140300835c80a4140400835c80a4140500835c80a4140600835c80a4140700835c80a4140800835c80a4140900835c80a4140a00835c80a4140b00835c80a4140c00835c80a4140d00835c80a4140e00835c80a4140f00835c80a414100000"_hex_v_u8, {{81970, 4684}, {10570, 604}, {10570, 604}, {10570, 604}, {10570, 604}, {10570, 604}, {10570, 604}, {10570, 604}, {10570, 604}, {10570, 604}, {10570, 604}, {10570, 604}, {10570, 604}, {10570, 604}, {10570, 604}, {10570, 604}, {10570, 604}, {10570, 604}}); - TestOptimalLinearization("83369734008331903c01a41680dd2e02b24989886c0380cb0a86fe4404a97680ff680582368c60068451a53407df7783c500088806b80c09a74a80f1660a841e9644080a823581c71e070a854cb37c09098236ee2e080a8452a534070a8753b2580b068235a104080a847ced5e090a831695740e06895080b7340b0a8312955e0c0a8478de000d088755d57e0e088908c0140f088235910210088500a6001603831199701208833da73013088545a6301b001b85419f541700178451a5340f1e8331b40e1218847cdc000e1b880682bf201800108a4880b84018010f85708088401611824183a3560b188541a52407358335b37c06278752b7220a1900228544a954002221896ac558001805001700"_hex_v_u8, {{82550, 6601}, {136779, 19257}, {12190, 1724}, {3399, 561}, {3390, 565}, {5567, 1109}, {2178, 437}, {2584, 573}, {27411, 6674}, {23563, 5932}, {2458, 721}, {4916, 1443}, {86513, 26559}, {1720, 529}, {2496, 768}, {4170, 1288}, {30286, 10050}, {3308, 1107}, {1466, 534}, {1455, 530}, {5420, 2104}, {1506, 670}}); - TestOptimalLinearization("83689e4c0085599314000083689e4c0100864cc014010185599314010183689e4c0201864cc014010300"_hex_v_u8, {{2022, 616}, {2022, 616}, {2022, 616}, {5460, 1829}, {5460, 1829}}); - TestOptimalLinearization("81c47cafb03400835bd8540000835bd8540100835bd8540200835bd8540300835bd8540400835bd8540500835bd8540600835bd8540700835bd8540800835bd8540900835bd8540a00835bd8540b00835bd8540c00835bd8540d00835bd8540e00835bd8540f00835bd8541000835bd8541100835bd8541200835bd8541300835bd8541400835bd8541500835bd8541600835bd8541700835bd8541800835bd8541900835bd8541a00835bd8541b00835bd8541c00835bd8541d00835bd8541e00835bd8541f00835bd8542000835bd8542100835bd8542200835bd8542300835bd8542400835bd8542500835bd8542600835bd8542700835bd8542800835bd8542900835bd8542a0000"_hex_v_u8, {{643112, 67653}}); - TestOptimalLinearization("83359d2c0083359d2c000083359d2c000283359d2c000283359d2c000200"_hex_v_u8, {{1942, 565}, {1942, 565}, {1942, 565}, {1942, 565}, {1942, 565}}); - TestOptimalLinearization("a335b4af0400832f85b3280000832f85b3280100832f85b3280200832f85b3280300832f85b3280400832f85b3280500832f85b3280600832f85b3280700832f85b3280800832f85b3280900832f85b3280a00832f85b3280b00832f85b3280c00832f85b3280d00832f85b3280e00832f85b3280f00832f85b3281000832f85b328110000"_hex_v_u8, {{1382250, 14723}}); - TestOptimalLinearization("833284fd3a00833581fc3801823684d50e02833181fb500383358695480480d77881b6f12005857c89bf7c0681a21d82999c300780d81d81b3ec6808844581a474098332899a7e0909833185bb04090984398190380809823587ae06070982358ddc1e080982368688220909823585cb000a09823586b3120b09823687aa6e0a0982359bf34a0b09823592ed040b09860880af480f05833286e0460b1d833185ba620b1c833288e64a0b1a833188a270022a833186bb5e0228833e89976a0225833186eb0a012b8332898512012783358a9130012d823986ff5a012883358a8f00012fed4996937e04020b000000000000000100"_hex_v_u8, {{272375, 2247}, {438299, 3939}, {46471, 438}, {353620, 3397}, {58788, 565}, {2916860, 29954}, {86078, 892}, {3665780, 38152}, {2692854, 28242}, {18810, 709}, {189759, 14153}, {11300, 904}}); - TestOptimalLinearization("883180ae7800a37a81cc480001a37a81cc480100a37a81cc480204835aaa160101835aaa160102835aaa160301835aaa160401835aaa160501835aaa160601835aaa160602835aaa160900835aaa160901835aaa160a01835aaa160b01835aaa160c01835aaa160c02835aaa160e01835aaa160f01835aaa160f02835aaa161101835aaa161201835aaa161301835aaa161401835aaa161600835aaa161700835aaa161800835aaa161702835aaa161802835aaa161902835aaa161c00835aaa161b02835aaa161e0000"_hex_v_u8, {{11260, 1201}, {62793, 13760}, {43452, 9546}, {37926, 8342}}); - TestOptimalLinearization("a25c81b56200832fa5000000832fa5000100832fa5000200832fa5000300832fa5000400832fa5000500832fa5000600832fa5000700832fa5000800832fa5000900832fa5000a00832fa5000b00832fa5000c00832fa5000d00832fa5000e00832fa5000f00832fa5001000832fa5001100832fa5001200832fa5001300832fa500140000"_hex_v_u8, {{70961, 16311}}); - TestOptimalLinearization("8368d63c00b273aaf80001842dec5e0101854e829f0201018f6681fb320103854e828b060300019e228ea20a0202835aea780206835aea780306835aea780406835aea780506835aea780606835aea780706835aea780806835aea780906835aea780a06842dec720a05836281a96a0a04836281a96a0b04836281a96a0c04836281a96a0d04836281a96a0e04836281a96a0f04836281a96a1004836281a96a1104836281a96a1204836281a96a1304836281a96a1404836281a96a1504836281a96a1604836281a96a1704836281a96a1804836281a96a1904836281a96a1a04836281a96a1b04836281a96a1c049d1e84a95e132200"_hex_v_u8, {{360000, 6643}, {26625, 846}, {488500, 15592}, {30945, 1462}, {93540, 8253}, {50728, 4555}}); - TestOptimalLinearization("80de6ebba3280081a442d1976601990e86a22a02996686ba6a0381cb6bdcce060480e358beea3205823590802e0506847480cb6c06058241e47a0705845280a22e0805824180ab2c09058241e5120a05854580fd100b05833580b34e0b058235919c180c05833280b8080d05823593c3700b0586048189660c05906383fd600d0582358db5100d0582358087700e05823a8088400f058242e47a10058241eb4016008235ec001304874f81ec4a1701860881896608198a77829b761700000e900f83e20e160002000300"_hex_v_u8, {{644225, 29540}, {935163, 43040}, {822655, 38007}, {641121, 29709}, {23397, 1103}, {11844, 562}, {11559, 565}, {8760, 437}, {8800, 442}, {16264, 837}, {17075, 900}, {17075, 904}, {40880, 2275}, {39111, 2191}, {59605, 3342}, {61173, 3430}, {13110, 756}, {26427, 1527}, {6976, 437}, {6944, 449}, {6537, 449}, {6525, 449}, {6525, 450}, {10455, 722}}); - TestOptimalLinearization("836280c06000836180c06001836280c06002834280b1600202836180c0600302834280b1600302836180c0600402834280b1600402836280c0600502877e81fc200509833a80b1600509836280c0600609877f81fc200608834180b1600608877e81fc200607836280c0600607834180b1600707836180c0600715834280b1600614836280c0600611836180c060050f834380b160050d834180b1600420834380b1600318834280b1600315836180c0600510836280c0600511877f81fc200428880281f96011030e836280c0600315836280c060022e834280b1600030836180c0600130880281fc20080710834280b1600132836280c060022e877f81fc200c0915833b80b1600131877e81fc2002022e877f81fc200a0610877e81fc20010230877f81fc2004110c877e81fc2000130d877f81fc2002110d877e81f96006021500"_hex_v_u8, {{96480, 4675}, {48240, 2338}, {48240, 2338}, {482080, 23373}, {12400, 609}, {12400, 610}, {12400, 610}}); - TestOptimalLinearization("818e6ca18c5000834fc8700001834fc8700100834fc8700200834fc8700300834fc8700400834fc8700500834fc8700600834fc8700700834fc8700800834fc8700900834fc8700a00834fc8700b00834fc8700c00834fc8700d00834fc8700e00834fc8700f00834fc8701000834fc8701100834fc8701200834fc8701300834fc8701400834fc8701500834fc8701600834fc8701700834fc8701800834fc8701900834fc8701a00834fc8701b00834fc8701c00834fc8701d00834fc8701e00834fc8701f00834fc8702000834fc8702100834fc8702200834fc8702300834fc8702400834fc8702500834fc8702600834fc8702700834fc870280000"_hex_v_u8, {{279400, 34796}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}}); - TestOptimalLinearization("8442872600c61981fd680000835a8c420000835a8c420100835a8c420200835a8c420300835a8c420400835a8c420500835a8c420600835a8c420700835a8c420800835a8c420900835a8c420a00835a8c420b00835a8c420c00835a8c420d00835a8c420e00835a8c420f00835a8c421000835a8c421100835a8c421200835a8c421300835a8c421400835a8c421500835a8c421600835a8c421700835a8c42180000"_hex_v_u8, {{25031, 9819}, {865, 602}, {865, 602}, {865, 602}, {865, 602}, {865, 602}, {865, 602}, {865, 602}, {865, 602}, {865, 602}, {865, 602}, {865, 602}, {865, 602}, {865, 602}, {865, 602}, {865, 602}, {865, 602}, {865, 602}, {865, 602}, {865, 602}, {865, 602}, {865, 602}, {865, 602}, {865, 602}, {865, 602}, {865, 602}}); - TestOptimalLinearization("8540e74000833180831801875dd14e00000000"_hex_v_u8, {{8460, 561}, {6688, 832}, {5287, 1117}}); - TestOptimalLinearization("808a5292d06800835ad3780000835ad3780100835ad3780200835ad3780300835ad3780400835ad3780500835ad3780600835ad3780700835ad3780800835ad3780900835ad3780a00835ad3780b00835ad3780c00835ad3780d00835ad3780e00835ad3780f00835ad3781000835ad3781100835ad3781200835ad3781300835ad3781400835ad3781500835ad3781600835ad3781700835ad3781800835ad3781900835ad3781a00835ad3781b00835ad3781c0000"_hex_v_u8, {{318528, 35332}}); - TestOptimalLinearization("8a0d8a54008368843000008a0d8a5401008368843000018a0d8a54010000836884300001996cc3320100008a449d1e00018d20a37e01000000"_hex_v_u8, {{11949, 12847}}); - TestOptimalLinearization("80ba1386a6640080c14d86cc1001809b10858b500280927684e2580380e9458893680480b6538695240580bb2086ac2006942981e1240000000000000000900e819b3a0100000000000000e2528bf6420200000000000000854dca54020200"_hex_v_u8, {{565214, 183924}}); - TestOptimalLinearization("80cc3fb8e500008327809a2000018327809a2001008327809a2002008327809a2003008327809a2004008327809a2005008327809a2006008327809a2007008327809a2008008327809a2009008327809a200a008327809a200b008327809a200c008327809a200d008327809a200e008327809a200f008327809a2010008327809a2011008327809a2012008327809a2013008327809a2014008327809a2015008327809a2016008327809a2017008327809a2018008327809a2019008327809a201a008327809a201b008327809a201c008327809a201d008327809a201e008327809a201f008327809a2020008327809a2021008327809a2022008327809a2023008327809a2024008327809a2025008327809a2026008327809a2027008327809a2028008327809a2029008327809a202a008327809a202b008327809a202c0000"_hex_v_u8, {{920592, 51098}}); - TestOptimalLinearization("83ea5fb6be1a0083c44cb2c86c0182ff47abfc140285940cc6dd7c038c3281d1740303841f80a25c0402870880f9740403833d809c400503896a81fb500603897680940608028a4c80b9560603836580941807038365819f0e0803833180874c0903851e80c0600d008331ad6e0c02833180874c0c0383358088480d03833180874c0e0383388089441101833880894412018338808944130183388089441500836180931c1501907d83ae781600158a4d81e82c150010912a84831c16000f8335808848091583388089440616851e80c0600815907583ad001a00000f91238aba401c000007833580884804208338808944041ca84c898e1c1e000000118235809e56042c83388089440220833180874c041e823580ee4c0331833180874c012200"_hex_v_u8, {{2460632, 356111}, {9539, 1398}, {2999, 561}}); - TestOptimalLinearization("8368aa5e008368aa5e018368aa5e028368aa5e02028368aa5e02028368aa5e0202836897260500836897260501a35780b6380106a35780b6380106836797080108836797080208836797080308836797080408836797080508836797080608836797080708836797080808836797080908836797080a08836797080b08836797080c08836797080d08836797080e08836797080f08836797081008836797081108836797081208836797081308836797081408836797081407836797081507836797081607836797081707836797081807836797081907836797081a07836797081b07836797081c07836797081d07836797081e07836797081f078367970820078367970821078367970822078367970823078367970824078367970825078734cb0a2a00002a00"_hex_v_u8, {{2799, 616}, {2799, 616}, {2799, 616}, {2799, 616}, {2799, 616}, {2799, 616}, {4869, 1076}, {1555, 616}, {1555, 616}, {42540, 16995}, {39460, 15765}}); - TestOptimalLinearization("854887862000854887862000008548878a0000008548878a0000008548878d6000008548879520000000"_hex_v_u8, {{397920, 5040}}); - TestOptimalLinearization("8331f924008336fa1400008331f70e00008335f56200008331ee3000008336ef1600008335e17c00008335df62000000"_hex_v_u8, {{7826, 561}, {7882, 566}, {7687, 561}, {7601, 565}, {7128, 561}, {7179, 566}, {6334, 565}, {6193, 565}}); - TestOptimalLinearization("808962829f2c0083628d2c000183628d2c010183628d2c020083628d2c030083628d2c040083628d2c050083628d2c060083628d2c070083628d2c080083628d2c090083628d2c0a0083628d2c0b0083628d2c0c0083628d2c0d0083628d2c0e0083628d2c0f0083628d2c100083628d2c110083628d2c120083628d2c130083628d2c140083628d2c150083628d2c160083628d2c170083628d2c180083628d2c190083628d2c1a0083628d2c1b0083628d2c1c0083628d2c1d0083628d2c1e0083628d2c1f0083628d2c200083628d2c210083628d2c220083628d2c230083628d2c240083628d2c250083628d2c260000"_hex_v_u8, {{62448, 41552}}); - TestOptimalLinearization("b27883865800833e81de3601833ea76a029d1d8e1003af4f82e54804c06484911005ad2d82ce6006ae2c82d86007b10082f32808af3882e35809833eba080aa13681d7300bbc1283e2480ca41d81f3400d847088140d0d824180f0280e0d8331a67e0d0d865adf4a0d0d8241ab120c0d86088081540d0d833eaa600e0d854e88720f0d823580c4580e0d8541b9260f0d833ead6c100d8545c014110d8542885e120d823680cd00120d8446bc7c130d83319d42140d8544c658140d8546c658130d8474f034130c854dca56200083318199601b06833281a4021e04865982aa6c1e05854e81e8681c088239c9121d08847c81b4181d09844582987a1b0c854dca5622068608f1242504833e8a142505857ceb401f0c847caa4c23099254828a502c002a8335a7221e378574b95a1c338332ce7419328335ad1819328331d2241731854680f04628001b8235b706122c9260828a503200012c833db00a06548235d332044a833ea76a0931895080a07e023e80dd6690b7682d0000010000000000031100"_hex_v_u8, {{22491, 574}, {83836, 9123}, {72635, 9291}, {6944, 892}, {74024, 9613}, {77864, 10309}, {57207, 7689}, {51363, 6931}, {50808, 6964}, {41279, 5818}, {42972, 6497}, {8845, 1395}, {2825, 449}, {17265, 2817}, {4843, 845}, {4843, 845}, {3966, 710}, {4588, 836}, {4588, 838}, {5954, 1139}, {166740, 33283}, {4170, 837}, {2800, 574}, {7749, 1700}, {2613, 574}, {32469, 7383}, {2790, 764}, {1953, 561}, {714, 574}, {586, 752}, {633, 846}, {623, 834}}); - TestOptimalLinearization("a25c82906c00835fb17e0000835fb17e0100835fb17e0200835fb17e0300835fb17e0400835fb17e0500835fb17e0600835fb17e0700835fb17e0800835fb17e0900835fb17e0a00835fb17e0b00835fb17e0c00835fb17e0d00835fb17e0e00835fb17e0f00835fb17e1000835fb17e1100835fb17e1200835fb17e1300835fb17e140000"_hex_v_u8, {{25718, 4572}, {3263, 607}, {3263, 607}, {3263, 607}, {3263, 607}, {3263, 607}, {3263, 607}, {3263, 607}, {3263, 607}, {3263, 607}, {3263, 607}, {3263, 607}, {3263, 607}, {3263, 607}, {3263, 607}, {3263, 607}, {3263, 607}, {3263, 607}, {3263, 607}, {3263, 607}, {3263, 607}, {3263, 607}}); - TestOptimalLinearization("834180872600834a808726018361808b3c028362808b3c03877f81914c0303877e81914c0303834280804c0303834280804c030383618086500208836280841a04048342fc1001098342f97201088361808650020883628081640406877f819142030d8341fc10020b8362808906030b8342f754030a83618086500313877e8196160705088342fe2e030e83628086500218877e819142060906836280865003138346fc10050f8361809028031d83618086500317836180865003178341fc100612834bfc10051383418085080424836180925e05248362808650051d8361809028051c8342fc1006188343fc1008178342808726042d836180902804258347fc10051b8342808508012a877f81881008121c836280902800368342808508003600"_hex_v_u8, {{26297, 1728}, {26297, 1736}, {139807, 9456}, {8990, 610}, {68514, 4674}, {35240, 2406}, {26660, 1828}, {8835, 610}, {8294, 578}, {8151, 578}, {8008, 577}, {8008, 578}, {8008, 579}, {8008, 582}, {8008, 583}, {8370, 610}, {8008, 587}, {7722, 578}}); - TestOptimalLinearization("a44d9db27a00824081e92c0000824081e92c0100824081e92c0200824081e92c0300824081e92c0400824081e92c0500824081e92c0600824081e92c070000"_hex_v_u8, {{434605, 8397}}); - TestOptimalLinearization("880180cf2200829428c7e9180000831ce0040000831ce0040100831ce0040200831ce0040300831ce004040000"_hex_v_u8, {{13329, 1153}, {596620, 51880}, {6210, 540}, {6210, 540}, {6210, 540}, {6210, 540}, {6210, 540}}); - TestOptimalLinearization("f90bc0b7520080840cc7e7780194268aae4602823581931c0202823681931c0302857882dc2e0402857c82de400502823581911c0602860482e26407028236819f1e0802823984a6160902823681a11e0a02860082e55a0b02847082c60a0c02847482c60a0d02847482c60a0e02826684a6160f02847082b8721002824180f0721102852282a8341202850082af001302823681bf201402823581bf201402823681bf201502823681b9701602847c83df681702823581b1201802857882e55a1902860882b0401a02823681c9221b02852982b0241c02847c82e6781d02850082b32a1f01823983b1521e028235819b1e20018235a5441e208242848b1a1c1f8242889a3819238a4485a45424000a823480e96408218a4c85a4542500028d07e0bb1a1100000500001900"_hex_v_u8, {{2320269, 40741}, {38964, 764}, {21137, 438}, {20152, 438}, {19600, 437}, {18447, 438}, {18191, 437}, {31228, 764}, {129164, 3167}, {17678, 437}, {17678, 438}, {28281, 752}, {27925, 768}, {27648, 768}, {31149, 888}, {51562, 1476}, {31149, 896}, {51562, 1484}, {15481, 449}, {30551, 888}, {30688, 892}, {30962, 900}, {42756, 1245}, {27226, 802}, {27744, 904}, {2466, 437}}); - TestOptimalLinearization("8361a17a008430a138000000"_hex_v_u8, {{2237, 609}, {2204, 688}}); - TestOptimalLinearization("fc7d88962000f93b87f516018a50809c6401018235a10402018235f65203018236cd1004018a4c80bb6405018235956e06018604de2c07018332fc480801847cdc0009018336fc700a018a50809e340b0182418c540c01831dcf020d01893c809f400d018470df300e018474dc640f01857cdd4010018802c83811018608dc00120183159a0a14008578dc0015008600dc001501823acf7c0e15857cf12412128336b6760a14926881943019000400"_hex_v_u8, {{171970, 27015}, {134824, 24317}, {2178, 437}, {4700, 1154}, {1463, 437}, {1733, 533}, {874, 449}}); - TestOptimalLinearization("829428f0fe20008319809604000183198096040100831980960402008319809604030083198096040400831980960405008319809604060083198096040700831980960408008319809604090083198096040a0083198096040b0083198096040c0083198096040d0083198096040e0083198096040f008319809604100083198096041100831980960412008319809604130083198096041400831980960415008319809604160083198096041700831980960418008319809604190083198096041a0083198096041b0083198096041c0083198096041d0083198096041e0083198096041f008319809604200083198096042100831980960422008319809604230083198096042400831980960425008319809604260083198096042700831980960428008319809604290083198096042a0083198096042b0083198096042c0083198096042d0083198096042e0083198096042f0083198096043000831980960431008319809604320083198096043300831980960434008319809604350000"_hex_v_u8, {{933840, 51880}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}, {9666, 537}}); - TestOptimalLinearization("870180db6e00841580832400008416808d5400008416eb7800008416808d54000000"_hex_v_u8, {{14135, 1025}, {17596, 1323}, {16102, 1324}}); - TestOptimalLinearization("818f1c85840c0083208b08000083208b08010083208b08020083208b08030083208b08040083208b08050083208b08060083208b08070083208b08080083208b08090083208b080a0083208b080b0083208b080c0083208b080d0083208b080e0083208b080f0083208b08100083208b08110083208b08120083208b08130083208b08140083208b08150083208b08160000"_hex_v_u8, {{49478, 34844}, {772, 544}, {772, 544}, {772, 544}, {772, 544}, {772, 544}, {772, 544}, {772, 544}, {772, 544}, {772, 544}, {772, 544}, {772, 544}, {772, 544}, {772, 544}, {772, 544}, {772, 544}, {772, 544}, {772, 544}, {772, 544}, {772, 544}, {772, 544}, {772, 544}, {772, 544}, {772, 544}}); - TestOptimalLinearization("81b8668092af300080da66e0f02801a36e8dc30a0280e87af0a9080380de2bdfea4a0480d709ef9f1405860081bd40068332ee300780cb48f1a11c08844682a01808088235d7dc300908826580f94c0a08824180e7600b088316818b4c0c088235c39c320c08833e81a31a0d08833280dd240e08854d81ce401007824280e4421008854b8df30e100893588984141108824180ad041208847483e97c12088235bdb51c1308824280b2261408824180b27e1508824180f66e19058448829a1a1a05823580fc1c1a068235c6f26c1808823581b2221908823981fa1a1a08860982d7681b088336819f0e1c08875d82ba3e1d088235b28b2a1d08823a8188381e08824180be341f08823680ba662008857881bc0a20088235a6d9061f08823a81a1182008824280e45c2108833680de6e2208823a80b2022308833281e41a2c00845182806e2c0024833581ac261d32831d81d04e2224854582ea7a2b010e823980c408062c896483ae002a0404866283d5781717158e10878014210f011fab528cf5380e1f050900"_hex_v_u8, {{1406632, 29465}, {1934192, 40603}, {1338143, 28094}, {1360813, 28571}, {1479376, 31139}, {1261329, 26621}, {19665, 437}, {241164, 5561}, {18572, 442}, {22861, 562}, {16988, 442}, {54538, 1431}, {31485, 837}, {26700, 710}, {26317, 712}, {38797, 1075}, {15863, 449}, {24695, 721}, {65610, 1936}, {30260, 905}, {14896, 449}, {16038, 485}, {14702, 450}, {14689, 450}, {18701, 574}, {18439, 566}, {82250, 2648}, {40755, 1410}, {12019, 438}, {12250, 449}, {26939, 1007}, {35776, 1380}, {11457, 442}, {11519, 449}, {11475, 450}, {28383, 1117}, {14226, 562}, {11138, 449}, {40677, 1784}, {121204, 6276}}); - TestOptimalLinearization("80ba43afe456008b358582100180c16cb587240280d261c0c11a0380d924bbc75c04833180ad5805900e84e9260682359b9b5c060782398087040706823598f2560606823599eb60050684788199680606823594a33c0805823580a95e0905854081f70c0d02824183c8280e028eb06183c190480b00058a7183aa0c0a000400ad428fc3340d000000000800"_hex_v_u8, {{49352, 1589}, {692467, 25721}, {711083, 27542}, {655101, 25377}, {716126, 28377}, {10927, 437}, {18100, 760}, {135450, 5954}, {94469, 4272}, {8706, 441}, {4736100, 252129}}); - TestOptimalLinearization("a25c86f87e008362808722000083628087220100836280872202008362808722030083628087220400836280872205008362808722060083628087220700836280872208008362808722090083628087220a0083628087220b0083628087220c0083628087220d0083628087220e0083628087220f008362808722100083628087221100836280872212008362808722130000"_hex_v_u8, {{239571, 16772}}); - TestOptimalLinearization("864a828f7a008b6384a51401854181d76c02833180e754038431819c3a04892a87a42205894587ba5c06853981d44607861c81ca2c0107857881bb3a010785008193000306823582ee280505854e81ec5a0a000a853581e22c0014896183d36c0007000007833e80f734000e860481c37000098642829e5c0106078a588398500108854181e744010f9659899c24000707843a81ac70000e857881b50e010c860481fb26020788358393240210833180f7420012843e81b51a0011874082e014000807853581ea0a000f853681ea0a000f833e80fc66000e833580f924000e833580fe4c000d00"_hex_v_u8, {{99621, 1759}, {69358, 1349}, {594899, 21560}, {24339, 900}, {20792, 900}, {17664, 768}, {34408, 1496}, {21206, 924}, {20253, 888}, {19847, 888}}); - TestOptimalLinearization("818e6ca18c5000834fc8700001834fc8700100834fc8700200834fc8700300834fc8700400834fc8700500834fc8700600834fc8700700834fc8700800834fc8700900834fc8700a00834fc8700b00834fc8700c00834fc8700d00834fc8700e00834fc8700f00834fc8701000834fc8701100834fc8701200834fc8701300834fc8701400834fc8701500834fc8701600834fc8701700834fc8701800834fc8701900834fc8701a00834fc8701b00834fc8701c00834fc8701d00834fc8701e00834fc8701f00834fc8702000834fc8702100834fc8702200834fc8702300834fc8702400834fc8702500834fc8702600834fc870270000"_hex_v_u8, {{279400, 34796}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}, {4728, 591}}); - TestOptimalLinearization("c7128ac61a00837ae46e0000837ae46e0100837ae46e0200837ae46e0300837ae46e0400837ae46e0500837ae46e0600837ae46e0700837ae46e0800837ae46e0900837ae46e0a00837ae46e0b00837ae46e0c00837ae46e0d00837ae46e0e00837ae46e0f00837ae46e1000837ae46e1100837ae46e1200837ae46e1300837ae46e1400837ae46e1500837ae46e1600837ae46e1700837ae46e1800837ae46e1900837ae46e1a00837ae46e1b00837ae46e1c00837ae46e1d00837ae46e1e0000"_hex_v_u8, {{296758, 28888}}); - TestOptimalLinearization("8440881a0084408c5e000000"_hex_v_u8, {{1468, 1408}}); - TestOptimalLinearization("a22d80e478008e4be10000008e4be42e00029031f0120002903284fe200000d25c9b8d380000835b80c71c0002835b80c71c0102835b80c71c0202835b80c71c0300835b80c71c0400835b80c71c0500835b80c71c0600835b80c71c0700835b80c71c0800835b80c71c0900835b80c71c0a00835b80c71c0b00835b80c71c0c00835b80c71c0d00835b80c71c0e00835b80c71c0f00835b80c71c1000835b80c71c1100835b80c71c1200835b80c71c1300835b80c71c1400835b80c71c1500835b80c71c1600835b80c71c1700835b80c71c1800835b80c71c1900835b80c71c1a00835b80c71c1b00835b80c71c1c00835b80c71c1d00835b80c71c1e00835b80c71c1f00835b80c71c2000835b80c71c2100835b80c71c2200835b80c71c2300835b80c71c2400835b80c71c2500835b80c71c2600835b80c71c2700835b80c71c2800835b80c71c2900835b80c71c2a00835b80c71c2b00835b80c71c2c00835b80c71c2d00835b80c71c2e00835b80c71c2f00835b80c71c3000835b80c71c3100835b80c71c3200835b80c71c3300835b80c71c3400835b80c71c350000"_hex_v_u8, {{1006076, 56244}}); - TestOptimalLinearization("8472e52e008473e52e018473e52e028473e52e038472e52e048472f85c058472e77405058472e52e05058473e52e05058473e52e05058473e52e05058472fe0005058472ef1e050f8473809e14050e8473e874050d8239ad42060d8473809e14060c8472e874060b8472fb58060a847280b024061a847280837406188473e674061684738083740514847280b91405128473fb580424847380cd24031e8472fb58031a8472f85c03178473fb58032b8473f85c03238472f85c031e847380ab14031a8472f85c03318472f85c03288473fe0003228473fb58031d8472f85c03378473f85c011d8473f85c031c8472808028023c8472f85c021e8473f85c021f8473f85c01208473f85c00218e0b81d3280a03010514901a8089000c000502020800"_hex_v_u8, {{50602, 4526}, {196414, 18533}, {7980, 755}, {23898, 2262}, {15918, 1509}, {23856, 2262}, {15580, 1509}, {7790, 755}, {7790, 755}, {7790, 755}, {7790, 755}, {2977, 441}, {8832, 2202}}); - TestOptimalLinearization("8361c74a0084a108cec45c0000831cbe5e0000831cbe5e0100831cbe5e0200831cbe5e0300831cbe5e0400831cbe5e0500831cbe5e0600831cbe5e0700831cbe5e0800831cbe5e0900831cbe5e0a00831cbe5e0b00831cbe5e0c00831cbe5e0d00831cbe5e0e00831cbe5e0f00831cbe5e1000831cbe5e1100831cbe5e1200831cbe5e1300831cbe5e1400831cbe5e1500831cbe5e1600831cbe5e1700831cbe5e1800831cbe5e1900831cbe5e1a00831cbe5e1b00831cbe5e1c00831cbe5e1d00831cbe5e1e00831cbe5e1f00831cbe5e2000831cbe5e2100831cbe5e2200831cbe5e2300831cbe5e2400831cbe5e2500831cbe5e2600831cbe5e270000"_hex_v_u8, {{4645, 609}, {814790, 107880}}); - TestOptimalLinearization("8431e564008369a158018369a15c028369a162038550ae20048369a17a058501a94a068501a946078430e72e088369a178098500a93a0a842fe5640b8502a9360c8501a8740d83699f5a0e8431e5640f8431e564108369a144118550ae2211118737ba280a118369a178081183699f5a051183699e4605118374b1601204891ec536060b0682199b70021582199b70041482199b7006138540ab7c031a853fab76001db6219ddc1007000000000100000000000000000000001e00"_hex_v_u8, {{327699, 22688}, {3248, 628}, {1848, 409}, {1848, 409}, {1848, 409}, {2210, 617}, {10260, 2973}}); - TestOptimalLinearization("836881f0280088318cba380000a37a9986500000a37a9986500100a37a9986500200a37a9986500300835a82ae5c0303835a82ae5c0403835a82ae5c0503835a82ae5c0603835a82ae5c0703835a82ae5c0803835a82ae5c0903835a82ae5c0a03835a82ae5c0b03835a82ae5c0c03835a82ae5c0d03835a82ae5c0e03835a82ae5c0f03835a82ae5c1003835a82ae5c1103835a82ae5c1203835a82ae5c1303835a82ae5c1403835a82ae5c1503835a82ae5c1603835a82ae5c1703835a82ae5c1803835a82ae5c1903835a82ae5c1a03835a82ae5c1a02835a82ae5c1a02835a82ae5c1c01835a82ae5c1c02835a82ae5c1e01835a82ae5c1e02835a82ae5c2001835a82ae5c2002835a82ae5c2102835a82ae5c2301835a82ae5c2302835a82ae5c2402835a82ae5c2502835a82ae5c2701835a82ae5c2801835a82ae5c2901835a82ae5c2a01835a82ae5c2a02835a82ae5c2c01835a82ae5c2d01835a82ae5c2d02835a82ae5c2f01835a82ae5c3001835a82ae5c3101835a82ae5c3102835a82ae5c3301835a82ae5c330200"_hex_v_u8, {{133936, 1817}, {876600, 19178}, {627930, 13760}, {545040, 11954}, {213480, 4730}}); - TestOptimalLinearization("836884c43c00a30da899200000847285dd280000856c86e6180100853586aa700200846085c6400300853586aa70040085168686300500853a86af38060085238694080700844f85b4200800853b86af380900850985f8580a00850185ef480b00853d86b4000c00853c86af380d00855d86d8400e00853e86b4000f00845985c1781000846485cb081100844c85af581200853e86b4001300845085b420140000"_hex_v_u8, {{45406, 616}, {1043316, 14258}, {52560, 719}, {58692, 803}, {60444, 827}, {52268, 716}, {52560, 720}, {53728, 736}, {54020, 740}, {60444, 828}, {63948, 876}}); - TestOptimalLinearization("8369821a008369821a0185018272028369821a038369821a0485018272058431892e0685018272078369821a088431892e09850182720a850182720b855083280c855083280d8369821a0e8369821a0f8369821a108369821a1185028272128369821a138369821a148369821a1585508328168369821a17823d834a188369821a198369821a1a8369821a1b855083281c8430892e1d842f892e1e843086101f8369821a208369821a0e338369821a1b208b0586542218860b8a381a208550832811208e538870111d8550832809208737843609208369821a09208369821a1c0d8369821a09498369821a032b8369821a032a8369821a0b2283699e5a04298369821a032c9d7181ea04012d8369821a012f8359a46c012e8369821a0131833983380034bc5285e37a110000110000000000000000000000000020bf6983b65e09000200000400000000000000000000100900"_hex_v_u8, {{25744, 6035}, {2422, 601}, {61527, 21962}, {43202, 25453}, {899, 2420}, {205, 617}, {205, 617}, {205, 617}}); - TestOptimalLinearization("8089328682520083329b52000083329b52010083329b52020083329b52030083329b52040083329b52050083329b52060083329b52070083329b52080083329b52090083329b520a0083329b520b0083329b520c0083329b520d0083329b520e0083329b520f0083329b52100083329b52110083329b52120083329b52130083329b52140083329b52150083329b52160083329b52170083329b52180083329b52190083329b521a0083329b521b0083329b521c0083329b521d0083329b521e0000"_hex_v_u8, {{114400, 35136}}); - TestOptimalLinearization("872d8f58009928c064000089509a400000895d99700100860d90680200860a905e03008655921c0400872b936e0500857f904006008603904a07008608905408008602904a0900861f91100a00862591240b0000"_hex_v_u8, {{20428, 16489}}); - TestOptimalLinearization("8472cf14008472cf14018472cf14028473cf1402028473cf1401028472cf1403018472cf1401098472cf1403068473cf1402048473cf1402058473cf1402068472cf1402068472cf1402078472cf1402088473cf1402088472cf1402098473cf14020a8472cf14020a8472cf14010d8473cf14030b8473cf14020cb42181bf200d00010e8473cf14020e8472cf14040d8472cf14030e8472cf1402108473cf1402118473cf1402118473cf1402128472cf1402138472cf140213886f80845e090b01148473cf1402158472cf1404148472cf1403158472cf1402188472cf1402178473cf1402188472cf14021b8473cf14001b00"_hex_v_u8, {{5130, 754}, {5130, 754}, {5130, 754}, {5130, 754}, {25650, 3772}, {61560, 9053}, {46170, 6790}, {30780, 4527}, {5130, 755}, {5130, 755}, {29055, 8080}}); - TestOptimalLinearization("808967889a74008367a77400018367a77401008367a77402008367a77403008367a77404008367a77405008367a77406008367a77407008367a77408008367a77409008367a7740a008367a7740b008367a7740c008367a7740d008367a7740e008367a7740f008367a77410008367a77411008367a77412008367a77413008367a77414008367a77415008367a77416008367a77417008367a77418008367a77419008367a7741a008367a7741b008367a7741c008367a7741d0000"_hex_v_u8, {{154054, 36217}}); - TestOptimalLinearization("8335b816008335c44c00008335c44c00008331c40c00008335c44c00008335c44c00008335c44c00008335c44c0000833dc54800008335c44c00008331c40c00008335c44c00008335c44c00008335c44c00008335c44c00008335c44c0000833dc54800008331c40c00008331c40c00008335c44c00008335c44c00008335c44c00008335c44c000000"_hex_v_u8, {{101643, 12995}}); - TestOptimalLinearization("89c0788087d818008448c72800008448c72801008448c72802008448c72803008448c72804008448c72805008448c72806008448c72807008448c72808008448c72809008448c7280a008448c7280b008448c7280c008448c7280d008448c7280e008448c7280f008448c72810008448c72811008448c72812008448c72813008448c72814008448c72815008448c72816008448c72817008448c72818008448c72819008448c7281a008448c7281b008448c7281c008448c7281d008448c7281e008448c7281f008448c72820008448c72821008448c72822008448c728230000"_hex_v_u8, {{1119820, 172280}, {4628, 712}, {4628, 712}, {4628, 712}, {4628, 712}, {4628, 712}, {4628, 712}, {4628, 712}, {4628, 712}, {4628, 712}, {4628, 712}, {4628, 712}, {4628, 712}, {4628, 712}, {4628, 712}, {4628, 712}, {4628, 712}, {4628, 712}, {4628, 712}, {4628, 712}, {4628, 712}, {4628, 712}, {4628, 712}, {4628, 712}, {4628, 712}, {4628, 712}, {4628, 712}, {4628, 712}, {4628, 712}, {4628, 712}, {4628, 712}, {4628, 712}, {4628, 712}, {4628, 712}, {4628, 712}, {4628, 712}, {4628, 712}}); - TestOptimalLinearization("81c62aebef0200823580816a01819771dba4680280d371c4eb600381ac0ee3960604854080ae0c05845081ce140505823580a59b260605857c82bb400705824180e86008058a4884bc36090582428188380a05833182d3140b058235808f93460a05860881fc300b05832480c92c0c058332818f7a0c05860082b74c0d05844482c1160e058235ed82480f058545828578100583368186741105854c829a121205823980f8361205823981906e13058235809892121405845181b2001505833180f3481605823a8188141705860482b12c1921857c81f5401d00847c82a7201b038b7e84bf581c03824180ef6a1c04875382d1161f02826581ce621e04875385b93a2300854d83c1702400833e81ce202203823681bf182402823581bf182403823581bf182503823681bf182702823681bf182a00823681c75a270484448394622c00823581c75a2d00823981eb302e008a4484cd682533860482e96c2831824181e6282534845182fa5430012797518b902c310028833281b9381930845181dc44300018ad5688bd082e1b857c82dc2e075f823982ac58045c9b698c944e3500021d00"_hex_v_u8, {{2075276, 38979}, {2283550, 42896}, {1937047, 36390}, {1473556, 27686}, {23320, 441}, {22996, 449}, {34161, 708}, {21037, 437}, {21037, 438}, {52893, 1107}, {20492, 437}, {20492, 437}, {20492, 438}, {20492, 438}, {20492, 438}, {32490, 721}, {21489, 485}, {37048, 845}, {28811, 708}, {17527, 441}, {16970, 442}, {16988, 450}, {21456, 574}, {15963, 441}, {27152, 764}, {15413, 449}, {135287, 4031}, {59862, 1792}, {14960, 449}, {35776, 1123}, {121446, 3848}, {28198, 896}, {26313, 844}, {17469, 562}, {27798, 900}, {25020, 837}, {16890, 566}, {21450, 720}, {107879, 3689}, {19648, 721}, {45100, 1662}, {24408, 904}, {29835, 1107}, {23968, 892}, {12950, 548}, {33576, 1553}, {77700, 5974}}); - TestOptimalLinearization("8368aa5e008368aa5e018368aa5e028368aa5e038368aa5e0483689726058368aa5e05058368aa5e05058368aa5e05058368aa5e05058368aa5e05058368aa5e05058368972608038368aa5e010b854ea024080005a35780b638020ba35780b638010e83679708010d83679708020d83679708030d83679708040d83679708050d83679708060d83679708070d83679708080d83679708090d836797080a0d836797080b0d836797080c0d836797080d0d836797080e0d854eba7414001c836797080f1d83679708101d83679708111d83679708121d83679708131d83679708141d83679708151d83679708161d83679708171d83679708181d83679708191d836797081a1d836797081b1d836797081c1d836797081d1d836797081e1d836797081f1d83679708201d83679708211d8734cb0a2a0000308734cf280013112600"_hex_v_u8, {{2799, 616}, {2799, 616}, {2799, 616}, {2799, 616}, {2799, 616}, {2799, 616}, {2799, 616}, {2799, 616}, {2799, 616}, {2799, 616}, {3834, 846}, {4869, 1076}, {12293, 2924}, {1555, 616}, {2130, 846}, {41000, 16380}, {33300, 13305}}); - TestOptimalLinearization("8361ee3400877f80d86401877e80d864028362ee3403877e80d86404877e80d86405877e80d864068362ee34078341e5640707877e80d86408078362ee3408078362ee340807877f80d86408078346e56409078361ee3409078361ee340907877f80f97608078342e56409078361ee340b068361ee340918877e80f51809178346e5640a178360f80c0a168342e5640b168362ee340b158361f80c0a148341e5640b148361fa420b138342e5640c138361fa420a118341e5640b118343e5640b2c8361fa420c2c8361fa420a288341ee5c0b288361fa420a268342e5640b268361fa420b238343ee5c0c23877e80f5180b218343f07a0c21877f80f5180b1c8343f07a0c1c8341f07a0a42877e80f5180b42877f80f5180b3b8341f07a0c3b877e80f5180b378342f07a0c37877f80f5180b338341f07a0c33877f819a421e0a2d877f819a420a1511877f819b2c031921877e819a42061121877e819a42090c3b877e819a420b0737877e819a4203141600"_hex_v_u8, {{263296, 19845}, {267965, 20479}, {7293, 577}, {7293, 577}, {7293, 577}, {7293, 578}, {7293, 579}, {7293, 579}, {7150, 577}, {7150, 579}, {6578, 577}, {6578, 578}, {6578, 582}}); - TestOptimalLinearization("80de1a89c02e0080dd1c8aac460180d10789b70202b04282ee2803854da96204833da30005ae0e82d6200682429268078608ac7408833e973a09b4558397700a823589e10e0a0a8331b54c0b0a8335a0000c0a823588ec180c0a8544ac400d0a8242bd000d0a8235899b7e0e0a8546ac500f0a8544ac5011098242974e12098545d03a110a8331a42215058241974015068545d35c140883319d5017068578b37c130a8541d3261408f43185ba60120a82429b001607833282b6161a048235ac5a140a8336b87219068331b54c14288f1c81a34020001a8751bb1e2000178540ac341f001483359d6611228241cc781024833db67c101a8b708099280d1dbf3a85a62a2301021483319d4a0634833d9e1e0633dd3884c704230000108a58d654120f0a9e65829c580438880ff5100010208474e9700030894880bd1002013200"_hex_v_u8, {{59807, 6900}, {10201, 1286}, {5422, 837}, {173248, 27774}, {454202, 73978}, {39260, 7429}, {5967, 1134}, {13266, 2536}, {37285, 7306}, {61944, 14794}, {1792, 450}, {68941, 17522}, {5610, 1496}, {2112, 565}, {1575, 450}, {1960, 561}, {2920, 836}, {1568, 449}, {3855, 1105}, {1971, 565}, {1957, 561}, {2920, 838}, {2912, 836}, {7642, 2250}}); - TestOptimalLinearization("81903fc9ee3800819170cfe6520180d334bef35002819540d0d4480380da6ebdd94a0482359094100405823580a7120504823589bd760504847c819d100504823585f11c060482358d8d6a0604823589c62e0604823580b5520704a51586dd5008000000000000"_hex_v_u8, {{784665, 36085}, {764717, 35881}, {611877, 29016}, {598334, 28389}, {747940, 35621}, {63400, 4885}}); - TestOptimalLinearization("808963829f2c0083638d2c000183638d2c010083638d2c020083638d2c030083638d2c040083638d2c050083638d2c060083638d2c070083638d2c080083638d2c090083638d2c0a0083638d2c0b0083638d2c0c0083638d2c0d0083638d2c0e0083638d2c0f0083638d2c100083638d2c110083638d2c120083638d2c130083638d2c140083638d2c150083638d2c160083638d2c170083638d2c180083638d2c190083638d2c1a0083638d2c1b0083638d2c1c0083638d2c1d0083638d2c1e0083638d2c1f0083638d2c200083638d2c210083638d2c220000"_hex_v_u8, {{58776, 39148}}); - TestOptimalLinearization("8d29889718008368809064018368809064028d1386db10020292618bd5080302846380ac380301846380ac38030283688090640307854e80c6580500038360b8540403824182812a0503844682b6300603846380ac38040e8368809064050e8368809064050b846380ac38060a842ebf400609846380ac38031683688090640415846380ac380410846380ac38011a854e80c65802030b846380ac3800108368809064010e846280ac38000f8368809064010d846280ac38000e8368809064010e846380ac38000f00"_hex_v_u8, {{203813, 4811}, {28120, 710}, {63240, 1811}, {9330, 616}, {9330, 616}, {9330, 616}, {9330, 616}, {9330, 616}, {62880, 4156}, {11100, 738}, {11100, 738}, {11100, 739}, {11100, 739}, {11100, 739}, {11100, 739}, {11100, 739}, {11100, 739}, {11100, 739}, {11100, 739}, {11100, 739}, {3690, 608}, {4128, 686}}); - TestOptimalLinearization("81bd6f8dc370008544a9200180df1588f04e028541ac340380c97c88b0240480e74989ca6c0583359a38068608d7240606854ec40a070687128091760806941381c52009068608d7240a06854de8200b05a32081e9680c058445c4200d058335ad300e05823580b40e0f05875d80856810058450809a380f068578d60e10068545d03a11068546b63212068a54808b20130682419c7214068474b93e15068235a26216068608d7241706833ead6c1806823580840a19068242cd221a068754c4081b06847480971a19068235c5281a068a58809c641b068474d2101c068239c2041d06854cd11e1e06823aa16e1f06ab7282a6702006823580887621068608a22825028540af5224048500e23425048336c0502604823abf2627048235fa3a2804896a80984e2904823997162a048803bd7a2b04823a97082c0483329d4a2d048332b1343002857cd64028388d7c818d0033002d8500ca0022328452ec581d36845180804835011a8545b9541a368546c658242dac1f82811c3702178450af18360210a70de536270e10854dee6c2c0c0400"_hex_v_u8, {{248259, 59175}, {180475, 43031}, {27624, 6624}, {167256, 41844}, {116449, 30424}, {3113, 832}, {1547, 441}, {4029, 1155}, {1540, 442}, {1957, 562}, {1756, 565}, {2260, 904}, {6555, 5133}}); - TestOptimalLinearization("c554baaa4600835c82fa220000835c82fa220100835c82fa220200835c82fa220300835c82fa220400835c82fa220500835c82fa220600835c82fa220700835c82fa220800835c82fa220900835c82fa220a0000"_hex_v_u8, {{486115, 9044}, {32465, 604}, {32465, 604}, {32465, 604}, {32465, 604}, {32465, 604}, {32465, 604}, {32465, 604}, {32465, 604}, {32465, 604}, {32465, 604}, {32465, 604}}); - TestOptimalLinearization("8184258aa316008185018287740180f14981ea6c028183288285600381a93a82c0180481831082a64005818a4182b2460681884983ae0a0781911684fd2208857cc81608088950904409088a4480d3240a08823590e0460a0882358fba2e0a08823590d1380a08823593963a0a08823590ed140908823590ae680b07823584640b08823a9f540d078235846e100585159a640f078541886014038478b41015038a54f370120782368a7a1604823588be08190282358fde161308854188601408823ab9661a03823a85101a048544c0141906844487281c048332aa561b068239a6181b078944e9201b0882358ee5281b088540bf6c1c08850088001d088c5f934a1e088445be0e2601833587662206854ce25a26038236856c22088541c30c2a018332875e0d2a8444c554250408875dd152121716833d8776023080970e80e35a013a9c6d81aa082b0000000000002400"_hex_v_u8, {{188460, 36250}, {175929, 34601}, {161920, 31928}, {182991, 36239}, {179050, 35516}, {176697, 35119}, {179744, 35778}, {194089, 38639}, {169428, 33733}, {7480, 1492}, {19140, 3821}, {4170, 836}, {4150, 832}, {2795, 562}, {2090, 442}, {3400, 760}, {5913, 1950}, {1778, 789}, {765, 438}, {438, 438}, {563, 565}, {1130, 1135}, {392, 442}, {375, 437}, {370, 437}, {1122, 1360}, {14637, 19470}, {532, 708}, {576, 768}, {624, 833}, {1317, 1759}}); - TestOptimalLinearization("836880ed0e00d724a0e46400008430818630000084308186300100842c81846c02008430818630030084308186300400842c81846c0500842c81846c060084308186300700842c81846c080084308186300900842c81846c0a0084308186300b0084308186300c0084308186300d00842c81846c0e00842c81846c0f0084308186301000842c81846c11008430818630120000"_hex_v_u8, {{15239, 616}, {276850, 11300}, {16758, 684}, {16758, 684}, {16758, 684}, {16758, 684}, {16758, 684}, {16758, 684}, {16758, 684}, {16758, 684}, {16856, 688}, {16856, 688}, {16856, 688}, {16856, 688}, {16856, 688}, {16856, 688}, {16856, 688}, {16856, 688}, {16856, 688}, {16856, 688}, {16856, 688}}); - TestOptimalLinearization("d02a82c24800fe6b84ff6001de7983ff08028235930202028578e04803028336915204028a48809e3405028474829172060285409a3807028474e30c08028a48809e34090283128d3c0a0283118d3c0b028608e1700c028948fd600d02857ce4060e028a5880aa140e028542b5700f028a4480a70e100282359f0412018600e44012028600e8001302b62180aa301402854182ad48150282368f0216028a4cef3417028a50d65418028500ee761a018600e4401a028236a3041b0286538292241d018578eb021e01823684fe6c1e028235a9061e028478f1241f02857cee4020028474dd4021028236ad0623018235a50423028241f41824028235a104250282418f0225238a5480a83c2800188235900a1e20824181834e181e82359f3e270f8a5080b9002b01078241a9060d2700"_hex_v_u8, {{119706, 15443}, {6467, 892}, {178169, 24786}, {6244, 888}, {6328, 904}, {10202, 1480}, {10202, 1480}, {2947, 438}, {8112, 1352}, {2306, 438}, {90860, 18386}, {7194, 1484}, {3512, 834}, {5610, 1488}, {3272, 1003}, {1281, 437}, {1025, 438}, {1025, 449}, {1756, 832}, {2019, 966}, {926, 530}, {10968, 7073}}); - TestOptimalLinearization("80896681da040083668b04000183668b04010083668b04020083668b04030083668b04040083668b04050083668b04060083668b04070083668b04080083668b04090083668b040a0083668b040b0083668b040c0083668b040d0083668b040e0083668b040f0083668b04100083668b04110083668b04120083668b04130083668b04140083668b04150083668b04160083668b04170083668b04180083668b04190083668b041a0083668b041b0083668b041c0083668b041d0083668b041e0083668b041f0083668b04200083668b04210083668b04220083668b04230083668b04240083668b04250083668b04260083668b04270083668b04280083668b04290083668b042a0083668b042b0000"_hex_v_u8, {{56090, 44782}}); - TestOptimalLinearization("80ea55a1fc3c0080e47da4dc2c0180e159a1c3340280e411a4ca500380d35ba1f20c04823586f77404048a5080b00405048265994a0604823a994a07048242c90a08048500e91a0904823680830e0904850081884e0a0482358397480b048474d8080c0485208194460d048542bf6c0e04854dc40a0f048239c92010048335ad181203823585e33a1104853f80871812048474e80613048236e47a1304823582a2261404823582894414048241c86a1504854cc40a17038658d0301704854dc0641804865fc4601c00138546c3361c0109833eb00a041c8452ba141c0004875c80c2541e0002833ead6c032900"_hex_v_u8, {{386635, 31880}, {338487, 29454}, {351640, 30602}, {341304, 30204}, {311144, 27664}, {12522, 1116}, {4752, 441}, {4741, 450}, {4725, 449}, {8716, 831}, {6723, 756}, {6797, 768}, {11330, 1488}, {5700, 756}, {7562, 1418}, {5208, 984}, {3786, 722}, {4421, 845}, {2956, 565}, {4379, 838}, {2998, 574}, {4210, 845}, {4150, 834}, {4464, 991}, {1701, 442}, {1701, 485}}); - TestOptimalLinearization("83698158008570832e0183698158028361831403875387440483698158058369815806b95d82d2480785018222088369815809836981580a836981580b836981580c8669831a0d836981580e836198220f8369815810860b843211836981581111843083221111bf69a814111183698158121184308336121183698158101188018362101183698158130a836981580e108430883c0b1183698158092b8339836c092a83698158082983698158082883698158082583698158061f83698158061c83698158091883698158073b83698158073983698158052983698158042383698158042183698158044687538744052d83698158042d83698158042883698158034d83698158012a836981580329836981580252823d880c022b83698158013d83698158003e83698158003d857c8968050a1f823d8400013eb623c2281104000004010500000000000019a63281c2600b0100010203050000000f00"_hex_v_u8, {{29924, 7517}, {1617, 609}, {25754, 20468}, {754, 1062}, {546, 1107}, {1036, 2126}, {7609, 17367}, {1180, 3530}, {2634, 8297}, {172, 617}, {172, 617}}); - TestOptimalLinearization("836280c06000836180c06001836280c06002834280b1600202836180c0600302834280b1600302836180c0600402834280b1600402836280c0600502877e81fc200509833a80b1600509836280c0600609877f81fc200608834180b1600608877e81fc200607836280c0600607834180b1600707836180c0600715834280b1600614836280c0600611836180c060050f834380b160050d834180b1600420834380b1600318834280b1600315836180c0600510877f81fc200327880281f96010030d836280c060012b834280b160002c836180c060012c880281fc2006070e834280b160012e836280c060022a877f81fc200a0913833b80b160012d877e81fc2002022a877f81fc2009050e877e81fc2001022c877f81fc20040f0a877e81fc2000110b877f81fc20020f0b877e81f96006021100"_hex_v_u8, {{96480, 4675}, {48240, 2338}, {48240, 2338}, {482080, 23373}, {12400, 609}}); - TestOptimalLinearization("836880bf4000834c80b6600000836880bf400100834c80b6600001836880bf400101834c80b6600002836880bf400102834c80b6600003836880bf400103834c80b6600004836880bf400104834c80b6600005836880bf400105834c80b6600006836880bf400106834c80b6600007836880bf400107834c80b6600008836881b768010800"_hex_v_u8, {{130900, 6160}, {11760, 588}, {11760, 588}, {11760, 588}, {11760, 588}, {11760, 588}, {11760, 588}, {11760, 588}, {11760, 588}, {11760, 588}}); - TestOptimalLinearization("8369817400885084460183698174028369817403842482760485028244058501824406836981740783698174088550827609866883460a836981740b836981740c850282440d836981740e836981740f8550827610836983261183698326128550846613836983261483698326158501841c168501841c1783698326188550846619836981741a836983261b836983261c836983261d842486681e836983261f83698326208501841c2185508276228550827647850182442483698174258550827626836981742783698174288369817429836981742a866783462b836981742c836981742d836981742e836981742e2f956f9220152f873786240e2f8667855c142a8b0589240f23823d897c0453bc50d70c06000000000000000000000024bf66db78061e00000000000000000000000000000035c30085961a0200020b000000000000000000000000000000003500"_hex_v_u8, {{59283, 28013}, {7894, 15440}, {9513, 20143}, {466, 1079}, {430, 999}}); - TestOptimalLinearization("cc1b8ae36800d6628bd74401912d81d342028368d406038e54819144048f7481a73405af7687b42806d35e8aa12c078416ab0c088f4781d31609a42e85905a0909b53087da7c07098459e30a0809cc4789cd7e0709912881db4405098422de500509a84b8693220e000d901e828d56050f823cce0e030f9017828c2201158608809b340807000d901e81d8420116925282b97c080600020a901c81d8420117901f81d8420012ca088ab75202010102020200"_hex_v_u8, {{68948, 6262}, {127805, 11981}, {21771, 2119}, {44226, 4410}, {22113, 2207}, {146849, 14665}, {162611, 16557}, {31803, 3253}, {151865, 16609}, {6120, 674}, {216238, 23904}, {6405, 729}}); - TestOptimalLinearization("8530af0600853daf60018930cd0602893abe00038638b70204862db62805853da600068a39e134078531af060707853caf600707853ca60007078531af0607078530af0606078530a53808068332b77408078540e6600c04883cc62009078500dc3e0c058500dc3e0a078312bf5e0b07853caf600b198531af060b168a4cd6180a1682359d5e09148241a0200b11853caf6008138239be4c09138541bf6c0b0e853daf60072b8745bf1c06258530af06081d8751d50209148f4bfb581200188531af0604278530b53a03228500dc3e05208638ab68032d8332b774042c8531af0604298a4880a930032b853db940051f8c33e3640b10248931cd0605348235a44806348530b53a052a8570f4340423853ca600044387548091640430853db9400328937081fa741410002e8835c564033c8a4c80a9300b12168236b366012a8c3be4200a0e23894480997c021c138e4bf4180102308f1c80cc6e06020832853ca60001338654f55602298534a55001338824ce14003f853ca600003f00"_hex_v_u8, {{16424, 2763}, {9568, 1720}, {54506, 9812}, {11635, 2160}, {45440, 8447}, {20893, 4158}, {4150, 833}, {5505, 1105}, {7182, 1503}, {68976, 14854}, {1967, 437}, {11126, 2482}, {24695, 5526}, {13379, 3279}, {10034, 2836}, {2496, 828}}); - TestOptimalLinearization("80884d94bf40008349db4000018349db4001008349db4002008349db4003008349db4004008349db4005008349db4006008349db4007008349db4008008349db4009008349db400a008349db400b008349db400c008349db400d008349db400e008349db400f008349db4010008349db4011008349db4012008349db4013008349db4014008349db4015008349db4016008349db4017008349db4018008349db4019008349db401a008349db401b008349db401c008349db401d008349db401e008349db401f008349db4020008349db4021008349db4022008349db4023008349db4024008349db4025008349db4026008349db4027008349db4028008349db4029008349db402a008349db402b008349db402c008349db402d008349db402e008349db402f0000"_hex_v_u8, {{460320, 45693}}); - TestOptimalLinearization("80cc00829900008449c452018336c318028335b4200380c95c86c57004ce3488a30c0580b63281ed680683358c1a078477da46088336b37c0988728092340a8540955c0b9f0a82831c0c8474c2760c0c82359094240d0c8335b2160e0c8239af7e0f0c823aad50100c9738c840110c8478c3520e0c823581db200f0c82358ae40e100c847cbb000f0c8478cf74100c8331a006110c8311af5c120c82358dd418130c8239ab58140c8331b97c1708854d926018088478c32419088600cf401e048621b8701f048235b13a1c088336bc4a160c8242b01c1e048335b216142d8331b97c08268474d14c131b967e81f164040a0a000009bd6580a1061f00000000000000000f00"_hex_v_u8, {{5859, 759}, {4364, 566}, {76038, 10164}, {9434, 1266}, {187130, 27709}, {3774, 561}, {3774, 561}, {172985, 27560}, {4457, 713}, {209015, 34252}, {3408, 565}, {3118, 529}, {3275, 565}, {3275, 565}, {4393, 760}, {4347, 756}, {4370, 760}, {5152, 896}, {3840, 764}, {3704, 929}, {2115, 561}, {9990, 3884}, {1264, 845}, {845, 565}, {10371, 8037}}); - TestOptimalLinearization("cf0884cf6c008324a54400008324a54401008324a54402008324a54403008324a54404008324a54405008324a54406008324a54407008324a54408008324a54409008324a5440a008324a5440b008324a5440c008324a5440d008324a5440e0000"_hex_v_u8, {{46134, 10248}, {2466, 548}, {2466, 548}, {2466, 548}, {2466, 548}, {2466, 548}, {2466, 548}, {2466, 548}, {2466, 548}, {2466, 548}, {2466, 548}, {2466, 548}, {2466, 548}, {2466, 548}, {2466, 548}, {2466, 548}}); - TestOptimalLinearization("8474ad70008474ad70018470ad70028470ad70038470ad70048470ad70058470ad70068474ad70078474ad70088470ad70098474ad700a8474ad700b8474ad700c8470ad700d8474ad700e8474ad700fb83285d734000000000000000000000000000000000f00"_hex_v_u8, {{102810, 19414}}); - TestOptimalLinearization("a408f07c00832c8c320000832c8c320100832c8c320200832c8c320300832c8c320400832c8c320500832c8c320600832c8c320700832c8c320800832c8c32090083308c3e0a0083308c3e0b0083308c3e0c0083308c3e0d00832f8c3a0e00832f8c3a0f00832f8c3a1000832f8c3a1100832f8c3a1200832d8c341300832d8c341400832d8c341500832d8c34160000"_hex_v_u8, {{27053, 17567}}); - TestOptimalLinearization("8362861c00da64e1740000832a83460000832a83460100832e834a02008331834e0300832a83460400832a83460500832a83460600832a83460700832a83460800832a83460900832a83460a00832a83460b00832a83460c00832a83460d0000"_hex_v_u8, {{462, 610}, {6330, 11748}, {295, 561}, {291, 554}, {291, 554}, {291, 554}, {291, 554}, {291, 554}, {291, 554}, {291, 554}, {291, 554}, {291, 554}, {291, 554}, {291, 554}, {291, 554}, {293, 558}}); - TestOptimalLinearization("80df4cacb754009e3d87e13a0180f36aac8350028541808e5803833180867004833180ce0a05971285db6206ab6d8bbe0407854180f21608841280c278099a2e86ce3c0a83328086700ba81f8abc700c857c80ef360d860080fb000e8331809e140f857881922210ad498bfa16118331808e1a1281c806d98a341380d468ad813a148235a4fa741415824180a40015148239d05c1614823ad22017148236d1101714847480bc561714823980804018148235ace32819148331e7681a138236e35c1d11833580d5681e11854480c66a19148236f9301614833280a23e1c0d8331808612181285788187681514857c81a01a1414846681882e1414823a809620151482359ec46414148335f12e151482359392721514854480a5161614847c80f9502b008241e252191382358082122b02833df27e1130857c818b260b338578818b260b31854d80aa041d1105857c819222013d857881aa5403358a7581d40e3100000029857c81aa540133c92091aa5e2a0000000000000000011e823580a6480035a10988bb460103010b0e000000000d00"_hex_v_u8, {{13253, 561}, {707608, 30199}, {996428, 42555}, {743996, 31775}, {16040, 764}, {36126, 1780}, {88603, 4456}, {34788, 1780}, {542102, 27805}, {8393, 437}, {12540, 658}, {8288, 441}, {15563, 833}, {10463, 562}, {132850, 7145}, {10186, 561}, {70262, 3940}, {71837, 4029}, {55089, 3090}, {102338, 5741}, {94072, 5279}, {15387, 892}, {265139, 15986}, {12139, 756}, {8649, 561}, {12789, 836}, {6446, 438}, {6377, 449}, {31027, 2358}, {7319, 565}, {10946, 845}, {10635, 836}, {14131, 1134}, {5328, 442}, {5256, 438}, {5230, 441}}); - TestOptimalLinearization("846ea73e00846ebc68018540ab6602846ebc68038540ab6604846ebc6805846ea73e06846ebc68078540c33208846ebc6809846ea73e0a8540ab660b8540ab660c8517a9520a0c8517a9520a098517a952030c8540ab660e000e8540ab660e000d8540ab660d000d8540ab660e030a8540c3320d000d8540ab660e000d8540c3320d000c8540ab660e000c8540ab660b02098540ab660e00098540ab660a020d8540ab6601178540c3320e010a8540ab66021b8517c00c01198540ab6609071b8540ab660907178540ab660d02198540ab6609090d8540ab660e021b8540ab660c041b8540ab660a00178540ab660a04138540c3320702168540ab660605178540ab6604031b8540ab660411108540ab6601228540ab6605031a8540ab66020b168540ab66050e108653b72a0a00032800"_hex_v_u8, {{3956, 750}, {3956, 750}, {3956, 750}, {3956, 750}, {3956, 750}, {4377, 832}, {4377, 832}, {6968, 1582}, {17006, 4078}, {10111, 2496}, {20807, 5971}, {2591, 750}, {2591, 750}, {2729, 791}, {2729, 791}, {2867, 832}, {2867, 832}, {2867, 832}, {2867, 832}, {2867, 832}, {2867, 832}, {2867, 832}, {2867, 832}, {2867, 832}, {2867, 832}, {2867, 832}, {2867, 832}, {2867, 832}, {2867, 832}, {2867, 832}, {2867, 832}, {2867, 832}, {2867, 832}, {2867, 832}, {2867, 832}}); - TestOptimalLinearization("836880d74800836880d74801836880d74802836880d74803834c80cf100303836880d7480403834c80cf100403836880d7480503834c80cf100503836880d7480603836880d7480603834c80cf100703834c80cf10060d836880d748070d834c80cf10060c836880d748070c834c80cf10060b836880d748070b834c80cf10070a834c80cf100519836880d7480619836880d7480516834c80cf100616836880d7480513834c80cf100613834c80cf100423836880d7480523834c80cf10051e836880d748061e834c80cf100519836880d7480619834c80cf10042c836880d748052c834c80cf100426836880d7480526834c80cf10041f834c80cf100334834c80cf10022b887685bb3e0301010b0300"_hex_v_u8, {{316363, 12974}, {13320, 588}, {13320, 588}, {13320, 588}, {13320, 588}, {13320, 588}, {13320, 588}, {13320, 588}, {13320, 588}, {13320, 588}, {13320, 588}, {13320, 588}, {13320, 588}, {13320, 588}, {13320, 588}, {13320, 588}, {13320, 588}, {13320, 588}, {13320, 588}, {13320, 588}}); - TestOptimalLinearization("808934829e280083348c28000183348c28010083348c28020083348c28030083348c28040083348c28050083348c28060083348c28070083348c28080083348c28090083348c280a0083348c280b0083348c280c0083348c280d0083348c280e0083348c280f0083348c28100083348c28110083348c28120083348c28130083348c28140083348c28150083348c28160083348c28170083348c28180083348c28190083348c281a0083348c281b0083348c281c0083348c281d0083348c281e0083348c281f0083348c28200083348c28210083348c28220083348c28230083348c28240083348c28250083348c28260083348c28270083348c28280083348c28290083348c282a0000"_hex_v_u8, {{63216, 41968}}); - TestOptimalLinearization("80af1a838c0a0080b37b82af76018335854e028335a64e03867cb2760483358a0c0580cd6485e13206854c8f3a0606823586e37207068241894608068750901a0906857cf2400a06823aab020b06824194060c068541bc500d068608f3440e068241a2000e06854ebd420f06823588b41610068500e13e11068241a2501206894480c21413068500905a1406854d8f3a150683368766160683358a0c1306823a983a1306823586bd7e140685458f261506833da17616068242a0341321854dc0641d000a83318a02061d854dc064120d8751901a0124b524808a58091200000000000200"_hex_v_u8, {{128151, 26614}, {4001, 846}, {127437, 27752}, {2535, 565}, {116824, 26905}, {2235, 573}, {1629, 442}, {3323, 1020}, {1347, 449}, {3239, 1554}, {675, 449}, {1133, 768}, {2125, 1691}, {1053, 844}, {9363, 7513}, {1053, 845}, {1043, 837}, {1101, 1105}, {563, 566}}); - TestOptimalLinearization("818241dbac3c0081c70c809fe6240180d740e79b0c0280eb5af7b4420380bf15cec96a0480fa208081cf4c0580ee2bf89d3a06950d8a8d7e0780c557e3bb7c0881866980839b52098235829f6a090982359fbf3209098335818f5a0a098331818d620b09823596fa1e0b09847882bc280c09823580e97e0d09845081de320e09823592c7020e09847482d4420f0985428291041306824281ec6c1208847882955c12098235a1b3181209863083f66a1309823580fa20130982358fec3c1409823593a460140984788298581608823680dc761609824180d87c1807863d83f32e160982358fc3761709823596ca261709857c82de401809823a80805019098239cb261b088948ce1c1b09a04c90d5682400228449829160220015866083b07022010c845181fa581f000b875183ee50210304857c82f460082186618381462800001e896d849d302500001200"_hex_v_u8, {{1073483, 28599}, {974262, 25978}, {28500, 760}, {1176771, 31491}, {1583595, 42433}, {1276412, 34206}, {1159437, 31072}, {998800, 26825}, {1208196, 32597}, {16080, 437}, {35960, 992}, {25776, 713}, {39912, 1105}, {62800, 1784}, {26220, 760}, {15039, 437}, {26030, 760}, {24300, 721}, {32931, 993}, {14203, 438}, {91071, 2829}, {22489, 720}, {13950, 449}, {17453, 565}, {17329, 561}, {42904, 1389}, {953801, 38788}, {8296, 442}, {4883, 441}, {5070, 1352}}); - TestOptimalLinearization("a91cb4e81c00fc20809ebc6801a454aef86e02ad6cbad74c03e044fba04e04c020d2950605a004a9893e06a004a9893e07a454aef86e089b38a39a1009a928b4e81c0a8d4c91cc040b8d4c91cc040c81940681dfa368000000000000000000000000000000"_hex_v_u8, {{440910, 5404}, {681347, 8352}, {152386, 1868}, {152386, 1868}, {488998, 5996}, {1017959, 12484}, {344735, 4228}, {344735, 4228}, {392823, 4820}, {392823, 4820}, {296648, 3640}, {1306484, 16032}, {440910, 5416}, {2885940, 35462}}); - TestOptimalLinearization("836181ba1c0088318bdc580000a34a97cd280000a34a97cd280100a34a97cd280200a34a97cd280300832a82965e0303832a82965e0403832a82965e0503832a82965e0603832a82965e0703832a82965e0803832a82965e0903832a82965e0a03832a82965e0b03832a82965e0c03832a82965e0d03832a82965e0e03832a82965e0f03832a82965e1003832a82965e1103832a82965e1203832a82965e1303832a82965e1403832a82965e1503832a82965e1603832a82965e1703832a82965e1803832a82965e1903832a82965e1a03832a82965e1902832a82965e1b01832a82965e1c01832a82965e1d01832a82965e1d02832a82965e1f01832a82965e1f02832a82965e2002832a82965e2201832a82965e2301832a82965e2302832a82965e2402832a82965e2502832a82965e2701832a82965e2801832a82965e2901832a82965e2a01832a82965e2a02832a82965e2b02832a82965e2d01832a82965e2d02832a82965e2f01832a82965e300100"_hex_v_u8, {{124474, 1810}, {827900, 17978}, {540855, 11884}, {462570, 10222}, {201620, 4682}}); - TestOptimalLinearization("921a84f92a008312809d6801841280c870028b7082891803945985e91004997e87ad7c0580b815ada40006941185c61807974d86cf62089f0a88f80209926d85932e0a963686a0560b945a85dc400c8d2183b53c0d9c5288972a0e9b4e87ee380f943585d12c108e1183d818119625869b5a128f3184896213911a84d154149305859a6415914284de0816980986e22e17920d84f54e18841280c2061818875c82817a1918854d818c5c1518823583bf4c1518861c818d101717857080d7481718866081cc2017188235fe2c1618866281d13e1518847880e9441518857880eb781318894c82b7781218850df5601018847c80ed601018854d80e51e0f18847480ed601018854280a71e1018850081a50002298d7f84983828000025dd44a5ec3425000025823980ac38014e866081f670022726ac7cc3fd5016000000000000000000000000000000000001042900"_hex_v_u8, {{1679688, 62029}, {24765, 1116}, {21663, 994}, {76772, 3548}, {21328, 992}, {28220, 1356}, {33551, 1613}, {17262, 845}, {790344, 39015}, {15280, 756}, {15280, 764}, {15010, 760}, {12483, 658}, {17288, 924}, {49284, 2640}, {8150, 437}, {15164, 888}, {13860, 880}, {10767, 834}, {7600, 781}}); - TestOptimalLinearization("836880832c00850d80a738000000"_hex_v_u8, {{19250, 1397}}); - TestOptimalLinearization("836883680084428f4c01836883680284428f4c03836883680483688368058368836806836883680783688368088368836809836883680a836883680b80a70f80a7100b0b809b7c809b7c0a0a809947809948090b809b3e809b40090b80a12b80a12c090b809a2d809a30090b809c0b809c0c090b809554809554090b809913809914090b809b53809b54090b854e80aa4c091f854e80a13a091c872d9804140111854e80a76a0a1b854e80a44e0a1a854e80a9000a19854e80a1440a18854e80a44a0a17854e809d0a0a16854e80a3140a15854e80a13c0a1484418f4c082e867a80c3560628854e8188060c131f854e81887c0c121d84428f4c033184428f4c0034854e80ea2a0d002c84418f4c012a867a80bc3407062b84418f4c012b84418f4c002984428f4c002684428f4c0023854e80a45003072284428f4c0123886080be340a020427854e80a300050620854ed83c05051d886080be7402090524854ed84600092900"_hex_v_u8, {{38835, 23106}, {40075, 24533}, {37668, 23160}, {110289, 72339}, {1062, 705}, {1062, 705}, {1062, 706}, {1062, 706}, {1062, 706}, {33045, 22510}, {30667, 21592}, {31176, 22039}, {26458, 22359}}); - TestOptimalLinearization("8a4481f65e008f7783dc7c00008f7783c70801008f6f83c70801008f7083c7080100008f7783bf620100008f7783bf620100008f7783bf620100008f7783c70801019b1686e862000200"_hex_v_u8, {{313375, 18069}, {36913, 2167}, {36913, 2167}}); - TestOptimalLinearization("dd5096a94c00db479a8f2201de64999944028236809310020285008082080302847c8083020402857c80830205028a5480d9140602847080f950070285008083020802857cfc38090283318c9b520a02823686d3220a02824187b83c0b02823680ad120c028236e65c0d028478fd180e028239c5640f028a5480d91410028a4880d60811028544e5301202854588ba341302847c8082641402823a87f5101402823687ab7e1502823680a1121602823580ad121702823680a7121802833e80c05e1902823ae9161a028241e1381b02850080966c1c0284788083361d028500fe641e02857c8083021f028a4480d9142002847cee0021028578ff7622028a4480d32423028500eb0024028a4c80cf582502833dc52826028a4c80d914280016824185df5e1128823a80ad1211288a4480cf582a000100"_hex_v_u8, {{431706, 13571}, {421921, 14027}, {11145, 437}, {11145, 438}, {11145, 442}, {10761, 438}, {299471, 12673}, {9480, 438}, {12399, 574}, {16040, 752}, {6795, 442}, {6638, 438}, {6300, 449}, {9718, 768}, {8475, 760}, {8449, 764}, {8434, 764}, {8449, 768}, {8388, 768}, {8178, 768}, {8076, 760}, {4530, 441}, {8449, 892}, {8449, 892}, {13962, 1476}, {13962, 1484}, {13962, 1492}, {13962, 1492}, {13764, 1480}, {7104, 764}, {8251, 888}, {13586, 1476}, {13356, 1476}, {6912, 768}, {8028, 892}, {13356, 1484}, {4500, 573}, {6552, 836}}); - TestOptimalLinearization("e05381ab28008756a16001904deb4a02a2608a900003971e81fb4604f32981e44005f179829b2606a51f80ea6a07e15182bc4208e55583b34e099029ed540a8d7adb1c0b882cc9200c8d29d72e0d9235f6600ef77284982a0f823581ea3c0f0f8235975c100b8600e1000c0f823582ab740d0f8265900c0e0f823581ed660e0f964181f340110d9838829b241609823a80cc6a100f857ceb40100f823580da10110f8474829172120f8235b94c130f8235fb58130f82419504160c82358c76140e82428c76150e85429632190b823980a002130f854480b348140f823580a61a140f80c7638487361e000418809e1a83c44421000000002080cf6484a24207130000000e9121d5361800000003020500"_hex_v_u8, {{91200, 4576}, {48195, 6111}, {29525, 3762}, {28266, 5337}, {79016, 15147}, {68868, 16192}, {4752, 1196}, {1582, 437}, {56602, 16222}, {53282, 15911}, {49862, 15150}, {44115, 13578}, {7082, 2217}, {1410, 449}, {5655, 1833}, {6949, 2253}, {5902, 1914}, {5531, 2337}, {1094, 485}, {891, 437}, {2224, 1110}, {891, 450}, {37218, 20378}, {1497, 834}, {43233, 26724}, {41499, 25699}}); - TestOptimalLinearization("80d25b87e93a0081fc0b8ef06a01d96182e34002d51082ca6603c36081ee3c04e02a83865e05d43882c72606c24581e7500780a61285fb1a08bc3f81c73409d87582df160ac74d8282560bce0f82a5480c808b3084ec3a0dc57681f96a0e80852c84cc0a0fce1482a54810be2b81d12011833e9c0011118241956e121183158e5013118450a3501311857c80b80414118242956e15118416ad3e1211857ced5e131182419b20141182399c3e1411847480971a1511880fde3414118544bc7614118331977015118336aa7e1511847cd30015118608f34416118449f54c1611854dc40a17118241a2141711844ab62c17118335993218118241921419118a5080b574181183369b4c1911847ca3001a11954880fc6026058451a540270583158e50193d8474808526183c8451a3502800218331aa56123483168e50035983168358005caa17c280442200000000000000000000000000000000002d00"_hex_v_u8, {{1360002, 282751}, {2975, 662}, {1887, 441}, {1808, 449}, {2464, 721}, {1463, 449}, {2344, 720}, {1463, 450}, {2344, 721}, {1856, 574}, {1830, 566}, {2304, 764}, {1689, 565}, {1592, 561}, {1226, 449}, {1000, 533}, {1000, 533}, {1000, 534}, {300, 534}}); + TestOptimalLinearization("9276fa3a009c3b80cd4001a21680d85c02927bfa5403934280845404a04c80cf0805c75b82c22206a46880f532079c7e80b85608965780916a09a04a80cf080a9823809b3e0bb27b81ec0c0c8540c60e0c0c993e80c86a0d0b8540c2020c0c9352809f780c09972f80f84a080c85449900080c875da164080c875081ae54070c8335af4c071f9c6781a72a13010f99108190160e000e85419f2c07168332903c05158540819e54041216ba5183907a140000001182428d080024a25c83c11201040400010609b6668487240004060000000000"_hex_u8, {3, 0, 1, 2, 4, 28, 29, 5, 16, 10, 12, 22, 24, 9, 14, 11, 13, 17, 19, 18, 27, 6, 7, 8, 20, 30, 21, 15, 25, 23, 26}); + TestOptimalLinearization("850d81fd4000850e81fd400000850d81fd400000850d81fd400000850e8285000000850d8285000000850e8288600000850e8288600000850e828860000000"_hex_u8, {0, 1, 2, 3, 4, 5, 6, 7, 8}); + TestOptimalLinearization("818f1c8a935a0083219530000083219530010083219530020083219530030083219530040083219530050083219530060083219530070083219530080000"_hex_u8, {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}); + TestOptimalLinearization("836880bf4000834c80b6600000836880bf400100834c80b6600001836880bf400101834c80b6600002836880bf400102834c80b6600003836880bf400103834c80b6600004836880bf400104834c80b6600005836880bf400105836880bf400006834c80b6600106834c80b6600106836880bf400206834c80b6600008836880bf400108836880bf40000900"_hex_u8, {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 14, 13, 15, 16, 17, 18, 19}); + TestOptimalLinearization("84a22e8fce380083208c38000083208c38010083208c38020083208c38030083208c38040083208c38050083208c38060083208c38070083208c38080083208c38090000"_hex_u8, {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}); + TestOptimalLinearization("8361a8340084309730000000"_hex_u8, {0, 1}); + TestOptimalLinearization("829428f0fe20008319809604000183198096040100831980960402008319809604030083198096040400831980960405008319809604060083198096040700831980960408008319809604090083198096040a0083198096040b0083198096040c0083198096040d0083198096040e0083198096040f008319809604100083198096041100831980960412008319809604130083198096041400831980960415008319809604160083198096041700831980960418008319809604190083198096041a0000"_hex_u8, {1, 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27}); + TestOptimalLinearization("854ec47200854ec4720001854ec4720001854ec4720001854ec4720001854ec4720001854ec4720001854ec4720001854ec4720001854ec4720000854ec4720000854ec4720000854ec4720000854ec4720000854ec4720000854ec4720000854ec4720000854ec4720000854ec4720000854ec4720000854ec4720000854ec4720000854ec4720000854ec4720000854ec472000000"_hex_u8, {8, 0, 1, 2, 3, 4, 5, 6, 7, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24}); + TestOptimalLinearization("d1378f927c00e81293cc4001f36095ef5202f20195c33203e93a93817404e76793d0700b80ba72a3e82806fd4697e52207da5d91894608c73d8d98401480990c9d954a0af73292e73a0b8090259bba640c808f689bac760de50692fc1e0eac40888c1a0fbf308bcf481080a3259f980c11c30282fd78128b6f83c2300612932d8ba65e0b09896a88837c010011886281d6380e0000040f953c8594580b000000129e0491c0381300000000148235f72802228653818c08021db40c9180620229833180991c011f854081a95c0020833180bd66002082418097740020953c8784000e00000000000201030d8d7c838d0c04011a874f84842a001600"_hex_u8, {13, 33, 0, 1, 2, 3, 4, 6, 7, 26, 27, 8, 9, 10, 11, 12, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 34, 30, 31, 32, 28, 29, 25, 35, 36}); + TestOptimalLinearization("836880ba5807845d80df200000836880ba580100845d80df200001836880bd0c0101845d80e2100002836880bf400102845d80e5000003836880bf400103845d80e5000004854e818800010300854e818800000300854e818800000200854e818800000100854e819178000000836880ed1c0000845f819b500017854e818b28001700"_hex_u8, {9, 10, 11, 13, 15, 16, 17, 18, 19, 14, 12, 20, 21, 22, 23, 24, 0, 1}); + TestOptimalLinearization("854e829b580088318881580000a37a90ae600000a37a90ae600100a37a90ae600200a37a90ae600300835a819e680303835a819e680403835a819e680503835a819e680603835a819e680703835a819e680803835a819e680903835a819e680a03835a819e680b03835a819e680c03835a819e680d03835a819e680e03835a819e680f03835a819e681003835a819e681103835a819e681203835a819e681303835a819e681403835a819e681503835a819e681603835a819e681703835a819e681803835a819e681903835a819e681a03835a819e681902835a819e681b01835a819e681c01835a819e681c02835a819e681e01835a819e681f01835a819e682001835a819e682002835a819e682102835a819e682301835a819e682302835a819e682501835a819e682502835a819e682602835a819e682801835a819e682802835a819e682a01835a819e682a02835a819e682b02835a819e682d01835a819e682d02835a819e682f01835a819e682f02835a819e683002835a819e68320100"_hex_u8, {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 28, 30, 33, 37, 38, 40, 42, 43, 45, 47, 48, 50, 52, 53, 27, 31, 32, 34, 35, 36, 39, 41, 44, 46, 49, 51, 54, 29}); + TestOptimalLinearization("83688095520089c17481b5cf780000842d809c700000842d809c700100842d809c700200842d809c700300842d809c700400842d809c700500842d809c700600842d809c700700842d809c700800842d809c700900842d809c700a00842d809c700b00842d809c700c00842d809c700d00842d809c700e00842d809c700f00842d809c701000842d809c701100842d809c701200842d809c701300842d809c701400842d809c701500842d809c701600842d809c701700842d809c701800842d809c701900842d809c701a00842d809c701b00842d809c701c00842d809c701d00842d809c701e00842d809c701f00842d809c702000842d809c702100842d809c702200842d809c702300842d809c702400842d809c702500842d809c702600842d809c702700842d809c702800842d809c702900842d809c702a00842d809c702b00842d809c702c00842d809c702d00842d809c702e00842d809c702f00842d809c703000842d809c703100842d809c703200842d809c70330000"_hex_u8, {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53}); + TestOptimalLinearization("99469a2e008e638f32018e638f32028e638718038e638718048e638718058e648c44068e659002078e639340088f74873c098e6488380a8d6586340b894784240c894784240d8b56852c0ea71993100f8b6d8538108b56852c118e628b76128e638b76138e638b76148e628b76158e648b7616a06c8f78178e638b76188e628838198e638b761a8e6388381b894784241c9412894c1d8e6690521e9c538e1c05199b10f15017000400189527955a1a0000000000001a9e5d8e70120000000000000117b372993c000300000000000000000000000000001800"_hex_u8, {9, 8, 1, 2, 10, 34, 0, 6, 22, 25, 23, 24, 28, 30, 26, 3, 4, 5, 7, 29, 31, 12, 35, 33, 11, 20, 13, 17, 16, 21, 27, 14, 15, 32, 18, 19}); + TestOptimalLinearization("833583380083368338000083328334000083318334000083328334000083368338000083358338000083328334000000"_hex_u8, {0, 1, 2, 3, 4, 5, 6, 7}); + TestOptimalLinearization("80f96f88ab2a008235839b0600008a4880b31801008604ec3c02008235a97c0300833dab7204008752d502050000"_hex_u8, {0, 1, 2, 3, 4, 5, 6}); + TestOptimalLinearization("f9718def4800823ab01c01833980c238028544848f20038478e07c04887280ef2a05823680a54e068081149ea80a07808714ac995208823680a55c0980b85cbcdc020abb759acf180b8338fe680c82359eac280c0c824280a9620d0c857cf9400e0c823ae5520a0c823590c744090c823584ef14090c847c80a32a0a0c8451808b100b0c824280a9420a0c823580a52c0b0c823586bf2c0c0c857c8186200d0c847882c63a0d0c854081cf060e0c833880b66e0f0c8338808e40100b8368809552110b8241de74130a8242c34c1608894480bc48102a851e818356050e0fad56888c401d00000000198fe81c808fc7501a0000000410933d86e120031300000a00"_hex_u8, {7, 26, 27, 28, 20, 12, 21, 24, 23, 22, 0, 1, 2, 15, 16, 13, 14, 6, 29, 25, 30, 31, 3, 4, 34, 32, 33, 17, 35, 10, 11, 18, 8, 5, 9, 36, 19}); + TestOptimalLinearization("82369e200084459e200186569e200282369e200384459e200488649e200586559e200684459e200788649e200886549e200984449e200a82369e200b9961dc600ca34b81da7800000000000000000000000000008368af4c0000869520c6dd6800008368af3800008368af3801008368af3802008368af3803008368af3804008368af3805008368af3806008368af3807008368af3808008368af3809008368af380a008368af380b008368af380c008368af380d008368af380e008368af380f0000"_hex_u8, {0, 3, 11, 10, 1, 4, 7, 9, 6, 2, 12, 5, 8, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31}); + TestOptimalLinearization("8335862e008335862e00008335862e00008335862e00008335862e00008335862e00008335862e00008335862e00008331862600008335862e00008335862e00008335862e00008335862e00008335862e00008335862e0000833d863a00008335862e00008335862e00008544896a000000"_hex_u8, {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18}); + TestOptimalLinearization("836183f20200842b84b82e00008a1089f33e0100842a849a7c00018361838f420101842b83ca680002836282f8280102842983b00c000300"_hex_u8, {0, 1, 2, 3, 4, 5, 6, 7}); + TestOptimalLinearization("80fc6c80fd300080e03c80f50e01823aaf3402823aac060380f42080f55e04833d84200580ea0580ea6006833e855a0780ce7c81b724088235898b1c08088474bd2c0908875180a10e0a08857cb0000b088239ad260c088336b8180d0889448e660e08823588db0e0e088242ac5a0c08823588df180d08854588660e088478d670120584498a440f08833dbb1e0f088474ea3810088470d83a1108823588ac7812088242844a13088546886614088545d67e1705823a84181b02875c8c0a1707854088601a058241ae3c1b05823587a67e180887548b7e19088241ae3c21018600d6401b08823a84141c088336854825008755f34a1e088335b6001c2d81d25ca2f16e27001e902d80ea6a250318894ce9202206068336d140034c9969829e282800001d82f57fb48c2e260000040e00"_hex_u8, {13, 14, 31, 22, 10, 11, 21, 42, 24, 28, 26, 27, 25, 0, 1, 3, 12, 32, 7, 8, 5, 6, 2, 15, 17, 18, 20, 37, 33, 16, 38, 39, 46, 43, 41, 4, 23, 29, 34, 36, 40, 35, 9, 19, 30, 44, 45}); + TestOptimalLinearization("80e67480e6740080d53480d56e0180d04881bd62028f108f1c038335cb7204847ce13e0404824184240504823594990c0604823580d07c07048235a6160804857cdd4009048474f2640904823592ce5c0a04833692700b048540ad300d038608b37c0c04823583e0720d048500a9000e048239841c0f048242b70011038540cc681203833e855a13038470bf7c13048545956a16008600be000d1a8f1880990a17000d8a448a4c1600048544f63c1603018f18f1180c0d0b8600ac40041f00"_hex_u8, {27, 0, 3, 4, 28, 1, 6, 8, 10, 9, 21, 22, 5, 12, 7, 13, 20, 14, 16, 24, 15, 17, 18, 11, 29, 19, 2, 23, 25, 26}); + TestOptimalLinearization("84418c6a0080fe1d86fc00000080b97084ea50000080de1c85fc00010080ed4986b930020080a17b848a70030080d07b85c670040080a86b84a630050080e405869320060080db1185ef50070080d11b85c770080080d00185c310090000"_hex_u8, {0, 1, 2, 3, 11, 9, 8, 4, 5, 7, 6, 10}); + TestOptimalLinearization("856ea51800856da5180000856eab080002856eab080002856dab080002856dab08000000"_hex_u8, {3, 4, 0, 1, 2, 5}); + TestOptimalLinearization("83318c2a00833d8c400183318c1c0283318c1c020283318c1c020283358c28020283318c1e020683318c1c020583318c1c0204833d8c40020a833d8c40020883318c1c020683318c1c020e83318c1c020b8331943e0208833d8c40021283318c1e020e83319a0c020a83358d58011183318c1e031083318d08011383318c1c0113833d8c40011583319a0c011483318c1c01169260809308021583358c280118a84380f9100a021383318c1c011983319430001983319938001983319a1c001883319a0c00188540a71609030683319a0c011983319a0c011283319a0c011283319a0c0113833d9a56011483319b52011483359a26011583359b6c011583319a0c011783319b52011683319a0c011983319b52011783319b52011b83319b520118833d9d6a001983309d18001900"_hex_u8, {0, 1, 2, 28, 29, 30, 31, 32, 33, 3, 4, 5, 16, 20, 27, 34, 35, 38, 43, 44, 45, 46, 47, 48, 49, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 23, 17, 18, 19, 21, 22, 24, 25, 26, 36, 37, 39, 40, 41, 42}); + TestOptimalLinearization("80886c99f50c00835df5600000835df5600100835df5600200835df5600300835df5600400835df5600500835df5600600835df5600700835df5600800835df5600900835df5600a00835df5600b00835df5600c00835df5600d00835df5600e00835df5600f00835df5601000835df5601100835df5601200835df5601300835df5601400835df5601500835df5601600835df5601700836880cd78180080895badcb740018835b80c9740018835b80c9740118835b80c9740218835b80c9740318835b80c9740418835b80c9740518835b80c9740618835b80c9740718835b80c9740818835b80c9740918835b80c9740a18835b80c9740b18835b80c9740c18835b80c9740d18835b80c9740e18835b80c9740f18835b80c9741018835b80c974111800"_hex_u8, {0, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24}); + TestOptimalLinearization("8514d518008344be3800008514d51801008344be3800018514d51801018514d51800028344be3801028344be3801028514d51802028344be3800048514d51801048344be3800058514d51801058514d51800068344be3801068344be3801068514d51802068344be3800088514d51801088344be3800098514d51801098514d518000a00"_hex_u8, {0, 1, 2, 3, 4, 6, 5, 7, 8, 9, 10, 11, 12, 14, 13, 15, 16, 17, 18, 19, 20, 21}); + TestOptimalLinearization("8442922e009069bd3a0000872d9c1a010083618f5e010183618f5e020183618f5e030183618f5e040183618f5e050183618f5e060183618f5e070183618f5e080183618f5e09019743a36609018442922e0a01835f8610010b835f8610020b835f8610030b835f8610040b835f8610050b835f8610060b835f8610070b835f8610080b835f8610090b835f86100a0b835f86100b0b835f86100c0b8442d82a0c0b8441e332001700"_hex_u8, {0, 11, 25, 26, 27, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24}); + TestOptimalLinearization("9420928e2c008368f11a0000c52488dd700000834acf100000834acf100100834acf100200834acf100300834acf100400834acf100500834acf100600834acf100700834acf100800834acf100900834acf100a00834acf100b00834acf100c00834acf100d00834acf100e00834acf100f00834acf101000834acf101100834acf101200834acf101300834acf10140000"_hex_u8, {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23}); + TestOptimalLinearization("9d2c83920200856cf66200008570f7280100856bf65202008567f60c03008563f54604008572f74c0500856ef7060600856af6400700856af64008008561f52209008566f57a0a008566f57a0b008575f8000c008571f73a0d008571f73a0e00856df6740f00856df67410008565f56811008561f522120000"_hex_u8, {0, 5, 4, 3, 11, 12, 8, 9, 7, 6, 10, 19, 18, 16, 17, 14, 15, 13, 1, 2}); + TestOptimalLinearization("854e80806600854e80806600008368e25000008462f54200008368e50601008463f8340001854e80b25c010000854e80b606000183688089400001846280a3620001854e80c00401000083688095520001846280b21c000100"_hex_u8, {0, 1, 2, 4, 5, 3, 6, 7, 8, 10, 11, 12, 9}); + TestOptimalLinearization("836186101483618872001583608842001584508d74001583618812011500"_hex_u8, {24, 0, 1, 2, 3}); + TestOptimalLinearization("8ee34aafe24c0083208c1a000083208c1a010083208c1a020083208c1a030083208c1a040083208c1a050083208c1a060083208c1a070083208c1a080083208c1a090083208c1a0a0083208c1a0b0083208c1a0c0083208c1a0d0083208c1a0e0083208c1a0f0083208c1a100083208c1a110083208c1a120083208c1a130083208c1a140083208c1a150083208c1a160083208c1a170083208c1a180083208c1a190083208c1a1a0083208c1a1b0083208c1a1c0083208c1a1d0083208c1a1e0083208c1a1f0083208c1a200083208c1a210083208c1a220083208c1a230083208c1a240083208c1a250083208c1a260083208c1a270083208c1a280083208c1a290083208c1a2a0083208c1a2b0083208c1a2c0083208c1a2d0083208c1a2e0083208c1a2f0083208c1a300083208c1a310083208c1a320083208c1a330083208c1a340083208c1a350083208c1a360083208c1a370083208c1a380083208c1a390083208c1a3a0083208c1a3b0000"_hex_u8, {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60}); + TestOptimalLinearization("a34c88ff6400835c80a4140000835c80a4140100835c80a4140200835c80a4140300835c80a4140400835c80a4140500835c80a4140600835c80a4140700835c80a4140800835c80a4140900835c80a4140a00835c80a4140b00835c80a4140c00835c80a4140d00835c80a4140e00835c80a4140f00835c80a414100000"_hex_u8, {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17}); + TestOptimalLinearization("83369734008331903c01a41680dd2e02b24989886c0380cb0a86fe4404a97680ff680582368c60068451a53407df7783c500088806b80c09a74a80f1660a841e9644080a823581c71e070a854cb37c09098236ee2e080a8452a534070a8753b2580b068235a104080a847ced5e090a831695740e06895080b7340b0a8312955e0c0a8478de000d088755d57e0e088908c0140f088235910210088500a6001603831199701208833da73013088545a6301b001b85419f541700178451a5340f1e8331b40e1218847cdc000e1b880682bf201800108a4880b84018010f85708088401611824183a3560b188541a52407358335b37c06278752b7220a1900228544a954002221896ac558001805001700"_hex_u8, {5, 29, 19, 30, 23, 26, 34, 27, 38, 42, 10, 36, 24, 33, 35, 22, 41, 31, 32, 11, 12, 16, 17, 18, 7, 9, 40, 39, 37, 3, 0, 1, 2, 6, 8, 20, 21, 25, 28, 13, 14, 15, 4}); + TestOptimalLinearization("83689e4c0085599314000083689e4c0100864cc014010185599314010183689e4c0201864cc014010300"_hex_u8, {0, 3, 6, 1, 2, 4, 5}); + TestOptimalLinearization("81c47cafb03400835bd8540000835bd8540100835bd8540200835bd8540300835bd8540400835bd8540500835bd8540600835bd8540700835bd8540800835bd8540900835bd8540a00835bd8540b00835bd8540c00835bd8540d00835bd8540e00835bd8540f00835bd8541000835bd8541100835bd8541200835bd8541300835bd8541400835bd8541500835bd8541600835bd8541700835bd8541800835bd8541900835bd8541a00835bd8541b00835bd8541c00835bd8541d00835bd8541e00835bd8541f00835bd8542000835bd8542100835bd8542200835bd8542300835bd8542400835bd8542500835bd8542600835bd8542700835bd8542800835bd8542900835bd8542a0000"_hex_u8, {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43}); + TestOptimalLinearization("83359d2c0083359d2c000083359d2c000283359d2c000283359d2c000200"_hex_u8, {3, 4, 0, 1, 2}); + TestOptimalLinearization("a335b4af0400832f85b3280000832f85b3280100832f85b3280200832f85b3280300832f85b3280400832f85b3280500832f85b3280600832f85b3280700832f85b3280800832f85b3280900832f85b3280a00832f85b3280b00832f85b3280c00832f85b3280d00832f85b3280e00832f85b3280f00832f85b3281000832f85b328110000"_hex_u8, {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18}); + TestOptimalLinearization("833284fd3a00833581fc3801823684d50e02833181fb500383358695480480d77881b6f12005857c89bf7c0681a21d82999c300780d81d81b3ec6808844581a474098332899a7e0909833185bb04090984398190380809823587ae06070982358ddc1e080982368688220909823585cb000a09823586b3120b09823687aa6e0a0982359bf34a0b09823592ed040b09860880af480f05833286e0460b1d833185ba620b1c833288e64a0b1a833188a270022a833186bb5e0228833e89976a0225833186eb0a012b8332898512012783358a9130012d823986ff5a012883358a8f00012fed4996937e04020b000000000000000100"_hex_u8, {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 21, 20, 24, 22, 23, 25, 26, 28, 27, 29, 30, 31, 32, 33}); + TestOptimalLinearization("883180ae7800a37a81cc480001a37a81cc480100a37a81cc480204835aaa160101835aaa160102835aaa160301835aaa160401835aaa160501835aaa160601835aaa160602835aaa160900835aaa160901835aaa160a01835aaa160b01835aaa160c01835aaa160c02835aaa160e01835aaa160f01835aaa160f02835aaa161101835aaa161201835aaa161301835aaa161401835aaa161600835aaa161700835aaa161800835aaa161702835aaa161802835aaa161902835aaa161c00835aaa161b02835aaa161e0000"_hex_u8, {1, 2, 5, 7, 8, 9, 10, 13, 14, 15, 16, 18, 19, 21, 22, 23, 24, 4, 6, 11, 17, 20, 28, 29, 30, 32, 0, 12, 25, 26, 27, 31, 33}); + TestOptimalLinearization("a25c81b56200832fa5000000832fa5000100832fa5000200832fa5000300832fa5000400832fa5000500832fa5000600832fa5000700832fa5000800832fa5000900832fa5000a00832fa5000b00832fa5000c00832fa5000d00832fa5000e00832fa5000f00832fa5001000832fa5001100832fa5001200832fa5001300832fa500140000"_hex_u8, {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21}); + TestOptimalLinearization("8368d63c00b273aaf80001842dec5e0101854e829f0201018f6681fb320103854e828b060300019e228ea20a0202835aea780206835aea780306835aea780406835aea780506835aea780606835aea780706835aea780806835aea780906835aea780a06842dec720a05836281a96a0a04836281a96a0b04836281a96a0c04836281a96a0d04836281a96a0e04836281a96a0f04836281a96a1004836281a96a1104836281a96a1204836281a96a1304836281a96a1404836281a96a1504836281a96a1604836281a96a1704836281a96a1804836281a96a1904836281a96a1a04836281a96a1b04836281a96a1c049d1e84a95e132200"_hex_u8, {12, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 0, 13, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 14, 15}); + TestOptimalLinearization("80de6ebba3280081a442d1976601990e86a22a02996686ba6a0381cb6bdcce060480e358beea3205823590802e0506847480cb6c06058241e47a0705845280a22e0805824180ab2c09058241e5120a05854580fd100b05833580b34e0b058235919c180c05833280b8080d05823593c3700b0586048189660c05906383fd600d0582358db5100d0582358087700e05823a8088400f058242e47a10058241eb4016008235ec001304874f81ec4a1701860881896608198a77829b761700000e900f83e20e160002000300"_hex_u8, {1, 0, 5, 15, 16, 8, 10, 20, 21, 28, 11, 9, 22, 23, 7, 17, 18, 19, 25, 12, 13, 2, 14, 27, 26, 6, 3, 24, 4}); + TestOptimalLinearization("836280c06000836180c06001836280c06002834280b1600202836180c0600302834280b1600302836180c0600402834280b1600402836280c0600502877e81fc200509833a80b1600509836280c0600609877f81fc200608834180b1600608877e81fc200607836280c0600607834180b1600707836180c0600715834280b1600614836280c0600611836180c060050f834380b160050d834180b1600420834380b1600318834280b1600315836180c0600510836280c0600511877f81fc200428880281f96011030e836280c0600315836280c060022e834280b1600030836180c0600130880281fc20080710834280b1600132836280c060022e877f81fc200c0915833b80b1600131877e81fc2002022e877f81fc200a0610877e81fc20010230877f81fc2004110c877e81fc2000130d877f81fc2002110d877e81f96006021500"_hex_u8, {0, 1, 2, 3, 4, 5, 18, 19, 20, 27, 28, 29, 10, 21, 30, 6, 8, 12, 14, 22, 32, 33, 11, 26, 15, 23, 35, 7, 16, 9, 17, 38, 13, 31, 34, 41, 24, 25, 37, 39, 36, 40, 42, 43, 44}); + TestOptimalLinearization("818e6ca18c5000834fc8700001834fc8700100834fc8700200834fc8700300834fc8700400834fc8700500834fc8700600834fc8700700834fc8700800834fc8700900834fc8700a00834fc8700b00834fc8700c00834fc8700d00834fc8700e00834fc8700f00834fc8701000834fc8701100834fc8701200834fc8701300834fc8701400834fc8701500834fc8701600834fc8701700834fc8701800834fc8701900834fc8701a00834fc8701b00834fc8701c00834fc8701d00834fc8701e00834fc8701f00834fc8702000834fc8702100834fc8702200834fc8702300834fc8702400834fc8702500834fc8702600834fc8702700834fc870280000"_hex_u8, {1, 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41}); + TestOptimalLinearization("8442872600c61981fd680000835a8c420000835a8c420100835a8c420200835a8c420300835a8c420400835a8c420500835a8c420600835a8c420700835a8c420800835a8c420900835a8c420a00835a8c420b00835a8c420c00835a8c420d00835a8c420e00835a8c420f00835a8c421000835a8c421100835a8c421200835a8c421300835a8c421400835a8c421500835a8c421600835a8c421700835a8c42180000"_hex_u8, {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26}); + TestOptimalLinearization("8540e74000833180831801875dd14e00000000"_hex_u8, {1, 0, 2}); + TestOptimalLinearization("808a5292d06800835ad3780000835ad3780100835ad3780200835ad3780300835ad3780400835ad3780500835ad3780600835ad3780700835ad3780800835ad3780900835ad3780a00835ad3780b00835ad3780c00835ad3780d00835ad3780e00835ad3780f00835ad3781000835ad3781100835ad3781200835ad3781300835ad3781400835ad3781500835ad3781600835ad3781700835ad3781800835ad3781900835ad3781a00835ad3781b00835ad3781c0000"_hex_u8, {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29}); + TestOptimalLinearization("8a0d8a54008368843000008a0d8a5401008368843000018a0d8a54010000836884300001996cc3320100008a449d1e00018d20a37e01000000"_hex_u8, {0, 1, 2, 3, 4, 6, 7, 5, 8}); + TestOptimalLinearization("80ba1386a6640080c14d86cc1001809b10858b500280927684e2580380e9458893680480b6538695240580bb2086ac2006942981e1240000000000000000900e819b3a0100000000000000e2528bf6420200000000000000854dca54020200"_hex_u8, {1, 3, 4, 5, 0, 2, 6, 9, 7, 10, 8}); + TestOptimalLinearization("80cc3fb8e500008327809a2000018327809a2001008327809a2002008327809a2003008327809a2004008327809a2005008327809a2006008327809a2007008327809a2008008327809a2009008327809a200a008327809a200b008327809a200c008327809a200d008327809a200e008327809a200f008327809a2010008327809a2011008327809a2012008327809a2013008327809a2014008327809a2015008327809a2016008327809a2017008327809a2018008327809a2019008327809a201a008327809a201b008327809a201c008327809a201d008327809a201e008327809a201f008327809a2020008327809a2021008327809a2022008327809a2023008327809a2024008327809a2025008327809a2026008327809a2027008327809a2028008327809a2029008327809a202a008327809a202b008327809a202c0000"_hex_u8, {1, 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45}); + TestOptimalLinearization("83ea5fb6be1a0083c44cb2c86c0182ff47abfc140285940cc6dd7c038c3281d1740303841f80a25c0402870880f9740403833d809c400503896a81fb500603897680940608028a4c80b9560603836580941807038365819f0e0803833180874c0903851e80c0600d008331ad6e0c02833180874c0c0383358088480d03833180874c0e0383388089441101833880894412018338808944130183388089441500836180931c1501907d83ae781600158a4d81e82c150010912a84831c16000f8335808848091583388089440616851e80c0600815907583ad001a00000f91238aba401c000007833580884804208338808944041ca84c898e1c1e000000118235809e56042c83388089440220833180874c041e823580ee4c0331833180874c012200"_hex_u8, {10, 15, 20, 23, 25, 24, 26, 28, 37, 38, 14, 12, 0, 4, 36, 21, 1, 2, 6, 7, 29, 30, 31, 32, 34, 35, 39, 3, 5, 33, 9, 27, 13, 16, 18, 11, 17, 19, 8, 22}); + TestOptimalLinearization("8368aa5e008368aa5e018368aa5e028368aa5e02028368aa5e02028368aa5e0202836897260500836897260501a35780b6380106a35780b6380106836797080108836797080208836797080308836797080408836797080508836797080608836797080708836797080808836797080908836797080a08836797080b08836797080c08836797080d08836797080e08836797080f08836797081008836797081108836797081208836797081308836797081408836797081407836797081507836797081607836797081707836797081807836797081907836797081a07836797081b07836797081c07836797081d07836797081e07836797081f078367970820078367970821078367970822078367970823078367970824078367970825078734cb0a2a00002a00"_hex_u8, {0, 1, 2, 3, 4, 5, 6, 7, 29, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48}); + TestOptimalLinearization("854887862000854887862000008548878a0000008548878a0000008548878d6000008548879520000000"_hex_u8, {0, 1, 2, 3, 4, 5}); + TestOptimalLinearization("8331f924008336fa1400008331f70e00008335f56200008331ee3000008336ef1600008335e17c00008335df62000000"_hex_u8, {0, 1, 2, 3, 4, 5, 6, 7}); + TestOptimalLinearization("808962829f2c0083628d2c000183628d2c010183628d2c020083628d2c030083628d2c040083628d2c050083628d2c060083628d2c070083628d2c080083628d2c090083628d2c0a0083628d2c0b0083628d2c0c0083628d2c0d0083628d2c0e0083628d2c0f0083628d2c100083628d2c110083628d2c120083628d2c130083628d2c140083628d2c150083628d2c160083628d2c170083628d2c180083628d2c190083628d2c1a0083628d2c1b0083628d2c1c0083628d2c1d0083628d2c1e0083628d2c1f0083628d2c200083628d2c210083628d2c220083628d2c230083628d2c240083628d2c250083628d2c260000"_hex_u8, {2, 0, 1, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39}); + TestOptimalLinearization("b27883865800833e81de3601833ea76a029d1d8e1003af4f82e54804c06484911005ad2d82ce6006ae2c82d86007b10082f32808af3882e35809833eba080aa13681d7300bbc1283e2480ca41d81f3400d847088140d0d824180f0280e0d8331a67e0d0d865adf4a0d0d8241ab120c0d86088081540d0d833eaa600e0d854e88720f0d823580c4580e0d8541b9260f0d833ead6c100d8545c014110d8542885e120d823680cd00120d8446bc7c130d83319d42140d8544c658140d8546c658130d8474f034130c854dca56200083318199601b06833281a4021e04865982aa6c1e05854e81e8681c088239c9121d08847c81b4181d09844582987a1b0c854dca5622068608f1242504833e8a142505857ceb401f0c847caa4c23099254828a502c002a8335a7221e378574b95a1c338332ce7419328335ad1819328331d2241731854680f04628001b8235b706122c9260828a503200012c833db00a06548235d332044a833ea76a0931895080a07e023e80dd6690b7682d0000010000000000031100"_hex_u8, {3, 28, 29, 50, 51, 30, 31, 40, 53, 43, 58, 0, 2, 4, 12, 48, 14, 11, 47, 56, 19, 45, 46, 34, 52, 36, 37, 38, 20, 21, 22, 23, 13, 16, 17, 49, 44, 54, 32, 35, 39, 24, 25, 41, 42, 26, 15, 5, 6, 7, 55, 8, 10, 9, 59, 33, 57, 1, 18, 27}); + TestOptimalLinearization("a25c82906c00835fb17e0000835fb17e0100835fb17e0200835fb17e0300835fb17e0400835fb17e0500835fb17e0600835fb17e0700835fb17e0800835fb17e0900835fb17e0a00835fb17e0b00835fb17e0c00835fb17e0d00835fb17e0e00835fb17e0f00835fb17e1000835fb17e1100835fb17e1200835fb17e1300835fb17e140000"_hex_u8, {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21}); + TestOptimalLinearization("834180872600834a808726018361808b3c028362808b3c03877f81914c0303877e81914c0303834280804c0303834280804c030383618086500208836280841a04048342fc1001098342f97201088361808650020883628081640406877f819142030d8341fc10020b8362808906030b8342f754030a83618086500313877e8196160705088342fe2e030e83628086500218877e819142060906836280865003138346fc10050f8361809028031d83618086500317836180865003178341fc100612834bfc10051383418085080424836180925e05248362808650051d8361809028051c8342fc1006188343fc1008178342808726042d836180902804258347fc10051b8342808508012a877f81881008121c836280902800368342808508003600"_hex_u8, {0, 1, 2, 3, 5, 6, 4, 7, 8, 9, 10, 11, 13, 14, 12, 15, 16, 17, 18, 19, 22, 23, 24, 20, 21, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 41, 40, 42}); + TestOptimalLinearization("a44d9db27a00824081e92c0000824081e92c0100824081e92c0200824081e92c0300824081e92c0400824081e92c0500824081e92c0600824081e92c070000"_hex_u8, {0, 1, 2, 3, 4, 5, 6, 7, 8}); + TestOptimalLinearization("880180cf2200829428c7e9180000831ce0040000831ce0040100831ce0040200831ce0040300831ce004040000"_hex_u8, {0, 1, 2, 3, 4, 5, 6}); + TestOptimalLinearization("f90bc0b7520080840cc7e7780194268aae4602823581931c0202823681931c0302857882dc2e0402857c82de400502823581911c0602860482e26407028236819f1e0802823984a6160902823681a11e0a02860082e55a0b02847082c60a0c02847482c60a0d02847482c60a0e02826684a6160f02847082b8721002824180f0721102852282a8341202850082af001302823681bf201402823581bf201402823681bf201502823681b9701602847c83df681702823581b1201802857882e55a1902860882b0401a02823681c9221b02852982b0241c02847c82e6781d02850082b32a1f01823983b1521e028235819b1e20018235a5441e208242848b1a1c1f8242889a3819238a4485a45424000a823480e96408218a4c85a4542500028d07e0bb1a1100000500001900"_hex_u8, {23, 24, 25, 0, 9, 17, 22, 10, 12, 5, 11, 14, 15, 16, 27, 28, 33, 26, 30, 8, 41, 35, 38, 39, 1, 2, 18, 37, 21, 31, 29, 13, 40, 19, 3, 4, 7, 34, 36, 20, 32, 6}); + TestOptimalLinearization("8361a17a008430a138000000"_hex_u8, {0, 1}); + TestOptimalLinearization("fc7d88962000f93b87f516018a50809c6401018235a10402018235f65203018236cd1004018a4c80bb6405018235956e06018604de2c07018332fc480801847cdc0009018336fc700a018a50809e340b0182418c540c01831dcf020d01893c809f400d018470df300e018474dc640f01857cdd4010018802c83811018608dc00120183159a0a14008578dc0015008600dc001501823acf7c0e15857cf12412128336b6760a14926881943019000400"_hex_u8, {0, 3, 8, 10, 11, 4, 15, 5, 12, 9, 13, 1, 7, 26, 16, 18, 19, 17, 23, 21, 27, 24, 20, 2, 22, 6, 25, 14}); + TestOptimalLinearization("829428f0fe20008319809604000183198096040100831980960402008319809604030083198096040400831980960405008319809604060083198096040700831980960408008319809604090083198096040a0083198096040b0083198096040c0083198096040d0083198096040e0083198096040f008319809604100083198096041100831980960412008319809604130083198096041400831980960415008319809604160083198096041700831980960418008319809604190083198096041a0083198096041b0083198096041c0083198096041d0083198096041e0083198096041f008319809604200083198096042100831980960422008319809604230083198096042400831980960425008319809604260083198096042700831980960428008319809604290083198096042a0083198096042b0083198096042c0083198096042d0083198096042e0083198096042f0083198096043000831980960431008319809604320083198096043300831980960434008319809604350000"_hex_u8, {1, 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54}); + TestOptimalLinearization("870180db6e00841580832400008416808d5400008416eb7800008416808d54000000"_hex_u8, {0, 1, 2, 3, 4}); + TestOptimalLinearization("818f1c85840c0083208b08000083208b08010083208b08020083208b08030083208b08040083208b08050083208b08060083208b08070083208b08080083208b08090083208b080a0083208b080b0083208b080c0083208b080d0083208b080e0083208b080f0083208b08100083208b08110083208b08120083208b08130083208b08140083208b08150083208b08160000"_hex_u8, {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23}); + TestOptimalLinearization("81b8668092af300080da66e0f02801a36e8dc30a0280e87af0a9080380de2bdfea4a0480d709ef9f1405860081bd40068332ee300780cb48f1a11c08844682a01808088235d7dc300908826580f94c0a08824180e7600b088316818b4c0c088235c39c320c08833e81a31a0d08833280dd240e08854d81ce401007824280e4421008854b8df30e100893588984141108824180ad041208847483e97c12088235bdb51c1308824280b2261408824180b27e1508824180f66e19058448829a1a1a05823580fc1c1a068235c6f26c1808823581b2221908823981fa1a1a08860982d7681b088336819f0e1c08875d82ba3e1d088235b28b2a1d08823a8188381e08824180be341f08823680ba662008857881bc0a20088235a6d9061f08823a81a1182008824280e45c2108833680de6e2208823a80b2022308833281e41a2c00845182806e2c0024833581ac261d32831d81d04e2224854582ea7a2b010e823980c408062c896483ae002a0404866283d5781717158e10878014210f011fab528cf5380e1f050900"_hex_u8, {28, 29, 31, 0, 2, 36, 37, 6, 7, 18, 20, 19, 46, 47, 30, 14, 15, 48, 54, 38, 27, 35, 40, 1, 26, 5, 25, 24, 10, 22, 32, 4, 3, 49, 12, 8, 33, 16, 11, 13, 41, 39, 50, 51, 53, 52, 23, 21, 34, 9, 17, 42, 43, 44, 45}); + TestOptimalLinearization("80ba43afe456008b358582100180c16cb587240280d261c0c11a0380d924bbc75c04833180ad5805900e84e9260682359b9b5c060782398087040706823598f2560606823599eb60050684788199680606823594a33c0805823580a95e0905854081f70c0d02824183c8280e028eb06183c190480b00058a7183aa0c0a000400ad428fc3340d000000000800"_hex_u8, {3, 1, 0, 14, 13, 6, 11, 4, 5, 7, 8, 12, 9, 10, 17, 16, 18, 2, 15}); + TestOptimalLinearization("a25c86f87e008362808722000083628087220100836280872202008362808722030083628087220400836280872205008362808722060083628087220700836280872208008362808722090083628087220a0083628087220b0083628087220c0083628087220d0083628087220e0083628087220f008362808722100083628087221100836280872212008362808722130000"_hex_u8, {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20}); + TestOptimalLinearization("864a828f7a008b6384a51401854181d76c02833180e754038431819c3a04892a87a42205894587ba5c06853981d44607861c81ca2c0107857881bb3a010785008193000306823582ee280505854e81ec5a0a000a853581e22c0014896183d36c0007000007833e80f734000e860481c37000098642829e5c0106078a588398500108854181e744010f9659899c24000707843a81ac70000e857881b50e010c860481fb26020788358393240210833180f7420012843e81b51a0011874082e014000807853581ea0a000f853681ea0a000f833e80fc66000e833580f924000e833580fe4c000d00"_hex_u8, {9, 31, 12, 1, 5, 6, 19, 4, 0, 2, 3, 7, 8, 10, 11, 13, 14, 15, 16, 18, 20, 21, 22, 24, 25, 27, 32, 28, 29, 30, 17, 26, 23}); + TestOptimalLinearization("818e6ca18c5000834fc8700001834fc8700100834fc8700200834fc8700300834fc8700400834fc8700500834fc8700600834fc8700700834fc8700800834fc8700900834fc8700a00834fc8700b00834fc8700c00834fc8700d00834fc8700e00834fc8700f00834fc8701000834fc8701100834fc8701200834fc8701300834fc8701400834fc8701500834fc8701600834fc8701700834fc8701800834fc8701900834fc8701a00834fc8701b00834fc8701c00834fc8701d00834fc8701e00834fc8701f00834fc8702000834fc8702100834fc8702200834fc8702300834fc8702400834fc8702500834fc8702600834fc870270000"_hex_u8, {1, 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40}); + TestOptimalLinearization("c7128ac61a00837ae46e0000837ae46e0100837ae46e0200837ae46e0300837ae46e0400837ae46e0500837ae46e0600837ae46e0700837ae46e0800837ae46e0900837ae46e0a00837ae46e0b00837ae46e0c00837ae46e0d00837ae46e0e00837ae46e0f00837ae46e1000837ae46e1100837ae46e1200837ae46e1300837ae46e1400837ae46e1500837ae46e1600837ae46e1700837ae46e1800837ae46e1900837ae46e1a00837ae46e1b00837ae46e1c00837ae46e1d00837ae46e1e0000"_hex_u8, {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31}); + TestOptimalLinearization("8440881a0084408c5e000000"_hex_u8, {0, 1}); + TestOptimalLinearization("a22d80e478008e4be10000008e4be42e00029031f0120002903284fe200000d25c9b8d380000835b80c71c0002835b80c71c0102835b80c71c0202835b80c71c0300835b80c71c0400835b80c71c0500835b80c71c0600835b80c71c0700835b80c71c0800835b80c71c0900835b80c71c0a00835b80c71c0b00835b80c71c0c00835b80c71c0d00835b80c71c0e00835b80c71c0f00835b80c71c1000835b80c71c1100835b80c71c1200835b80c71c1300835b80c71c1400835b80c71c1500835b80c71c1600835b80c71c1700835b80c71c1800835b80c71c1900835b80c71c1a00835b80c71c1b00835b80c71c1c00835b80c71c1d00835b80c71c1e00835b80c71c1f00835b80c71c2000835b80c71c2100835b80c71c2200835b80c71c2300835b80c71c2400835b80c71c2500835b80c71c2600835b80c71c2700835b80c71c2800835b80c71c2900835b80c71c2a00835b80c71c2b00835b80c71c2c00835b80c71c2d00835b80c71c2e00835b80c71c2f00835b80c71c3000835b80c71c3100835b80c71c3200835b80c71c3300835b80c71c3400835b80c71c350000"_hex_u8, {2, 3, 0, 1, 7, 8, 4, 5, 6, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59}); + TestOptimalLinearization("8472e52e008473e52e018473e52e028473e52e038472e52e048472f85c058472e77405058472e52e05058473e52e05058473e52e05058473e52e05058472fe0005058472ef1e050f8473809e14050e8473e874050d8239ad42060d8473809e14060c8472e874060b8472fb58060a847280b024061a847280837406188473e674061684738083740514847280b91405128473fb580424847380cd24031e8472fb58031a8472f85c03178473fb58032b8473f85c03238472f85c031e847380ab14031a8472f85c03318472f85c03288473fe0003228473fb58031d8472f85c03378473f85c011d8473f85c031c8472808028023c8472f85c021e8473f85c021f8473f85c01208473f85c00218e0b81d3280a03010514901a8089000c000502020800"_hex_u8, {29, 30, 31, 32, 33, 34, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 21, 22, 23, 24, 25, 28, 35, 36, 37, 38, 26, 27, 6, 7, 8, 40, 42, 41, 43, 44, 45, 20, 39}); + TestOptimalLinearization("8361c74a0084a108cec45c0000831cbe5e0000831cbe5e0100831cbe5e0200831cbe5e0300831cbe5e0400831cbe5e0500831cbe5e0600831cbe5e0700831cbe5e0800831cbe5e0900831cbe5e0a00831cbe5e0b00831cbe5e0c00831cbe5e0d00831cbe5e0e00831cbe5e0f00831cbe5e1000831cbe5e1100831cbe5e1200831cbe5e1300831cbe5e1400831cbe5e1500831cbe5e1600831cbe5e1700831cbe5e1800831cbe5e1900831cbe5e1a00831cbe5e1b00831cbe5e1c00831cbe5e1d00831cbe5e1e00831cbe5e1f00831cbe5e2000831cbe5e2100831cbe5e2200831cbe5e2300831cbe5e2400831cbe5e2500831cbe5e2600831cbe5e270000"_hex_u8, {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41}); + TestOptimalLinearization("8431e564008369a158018369a15c028369a162038550ae20048369a17a058501a94a068501a946078430e72e088369a178098500a93a0a842fe5640b8502a9360c8501a8740d83699f5a0e8431e5640f8431e564108369a144118550ae2211118737ba280a118369a178081183699f5a051183699e4605118374b1601204891ec536060b0682199b70021582199b70041482199b7006138540ab7c031a853fab76001db6219ddc1007000000000100000000000000000000001e00"_hex_u8, {10, 14, 1, 19, 21, 7, 12, 15, 5, 4, 3, 2, 6, 8, 9, 13, 16, 11, 17, 18, 20, 22, 0, 27, 28, 29, 30, 23, 24, 25, 26}); + TestOptimalLinearization("836881f0280088318cba380000a37a9986500000a37a9986500100a37a9986500200a37a9986500300835a82ae5c0303835a82ae5c0403835a82ae5c0503835a82ae5c0603835a82ae5c0703835a82ae5c0803835a82ae5c0903835a82ae5c0a03835a82ae5c0b03835a82ae5c0c03835a82ae5c0d03835a82ae5c0e03835a82ae5c0f03835a82ae5c1003835a82ae5c1103835a82ae5c1203835a82ae5c1303835a82ae5c1403835a82ae5c1503835a82ae5c1603835a82ae5c1703835a82ae5c1803835a82ae5c1903835a82ae5c1a03835a82ae5c1a02835a82ae5c1a02835a82ae5c1c01835a82ae5c1c02835a82ae5c1e01835a82ae5c1e02835a82ae5c2001835a82ae5c2002835a82ae5c2102835a82ae5c2301835a82ae5c2302835a82ae5c2402835a82ae5c2502835a82ae5c2701835a82ae5c2801835a82ae5c2901835a82ae5c2a01835a82ae5c2a02835a82ae5c2c01835a82ae5c2d01835a82ae5c2d02835a82ae5c2f01835a82ae5c3001835a82ae5c3101835a82ae5c3102835a82ae5c3301835a82ae5c330200"_hex_u8, {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 29, 32, 34, 36, 39, 43, 44, 45, 46, 48, 49, 51, 52, 53, 55, 28, 31, 33, 35, 37, 38, 40, 41, 42, 47, 50, 54, 56, 30}); + TestOptimalLinearization("836884c43c00a30da899200000847285dd280000856c86e6180100853586aa700200846085c6400300853586aa70040085168686300500853a86af38060085238694080700844f85b4200800853b86af380900850985f8580a00850185ef480b00853d86b4000c00853c86af380d00855d86d8400e00853e86b4000f00845985c1781000846485cb081100844c85af581200853e86b4001300845085b420140000"_hex_u8, {0, 1, 18, 13, 12, 4, 6, 14, 16, 2, 7, 8, 17, 21, 10, 9, 11, 20, 22, 5, 19, 15, 3}); + TestOptimalLinearization("8369821a008369821a0185018272028369821a038369821a0485018272058431892e0685018272078369821a088431892e09850182720a850182720b855083280c855083280d8369821a0e8369821a0f8369821a108369821a1185028272128369821a138369821a148369821a1585508328168369821a17823d834a188369821a198369821a1a8369821a1b855083281c8430892e1d842f892e1e843086101f8369821a208369821a0e338369821a1b208b0586542218860b8a381a208550832811208e538870111d8550832809208737843609208369821a09208369821a1c0d8369821a09498369821a032b8369821a032a8369821a0b2283699e5a04298369821a032c9d7181ea04012d8369821a012f8359a46c012e8369821a0131833983380034bc5285e37a110000110000000000000000000000000020bf6983b65e09000200000400000000000000000000100900"_hex_u8, {18, 49, 53, 54, 55, 8, 13, 14, 1, 3, 5, 6, 9, 11, 19, 20, 21, 17, 4, 7, 10, 15, 16, 12, 22, 39, 37, 42, 32, 23, 25, 27, 28, 30, 33, 34, 35, 43, 44, 45, 26, 29, 36, 38, 24, 40, 41, 31, 46, 48, 51, 52, 50, 0, 2, 47}); + TestOptimalLinearization("8089328682520083329b52000083329b52010083329b52020083329b52030083329b52040083329b52050083329b52060083329b52070083329b52080083329b52090083329b520a0083329b520b0083329b520c0083329b520d0083329b520e0083329b520f0083329b52100083329b52110083329b52120083329b52130083329b52140083329b52150083329b52160083329b52170083329b52180083329b52190083329b521a0083329b521b0083329b521c0083329b521d0083329b521e0000"_hex_u8, {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31}); + TestOptimalLinearization("872d8f58009928c064000089509a400000895d99700100860d90680200860a905e03008655921c0400872b936e0500857f904006008603904a07008608905408008602904a0900861f91100a00862591240b0000"_hex_u8, {0, 1, 2, 4, 13, 6, 11, 5, 3, 8, 9, 12, 7, 10}); + TestOptimalLinearization("8472cf14008472cf14018472cf14028473cf1402028473cf1401028472cf1403018472cf1401098472cf1403068473cf1402048473cf1402058473cf1402068472cf1402068472cf1402078472cf1402088473cf1402088472cf1402098473cf14020a8472cf14020a8472cf14010d8473cf14030b8473cf14020cb42181bf200d00010e8473cf14020e8472cf14040d8472cf14030e8472cf1402108473cf1402118473cf1402118473cf1402128472cf1402138472cf140213886f80845e090b01148473cf1402158472cf1404148472cf1403158472cf1402188472cf1402178473cf1402188472cf14021b8473cf14001b00"_hex_u8, {1, 4, 5, 8, 6, 0, 9, 13, 16, 2, 3, 10, 14, 17, 18, 23, 26, 29, 31, 33, 35, 12, 15, 19, 21, 24, 27, 30, 34, 36, 20, 22, 25, 28, 32, 37, 38, 39, 7, 11}); + TestOptimalLinearization("808967889a74008367a77400018367a77401008367a77402008367a77403008367a77404008367a77405008367a77406008367a77407008367a77408008367a77409008367a7740a008367a7740b008367a7740c008367a7740d008367a7740e008367a7740f008367a77410008367a77411008367a77412008367a77413008367a77414008367a77415008367a77416008367a77417008367a77418008367a77419008367a7741a008367a7741b008367a7741c008367a7741d0000"_hex_u8, {1, 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30}); + TestOptimalLinearization("8335b816008335c44c00008335c44c00008331c40c00008335c44c00008335c44c00008335c44c00008335c44c0000833dc54800008335c44c00008331c40c00008335c44c00008335c44c00008335c44c00008335c44c00008335c44c0000833dc54800008331c40c00008331c40c00008335c44c00008335c44c00008335c44c00008335c44c000000"_hex_u8, {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22}); + TestOptimalLinearization("89c0788087d818008448c72800008448c72801008448c72802008448c72803008448c72804008448c72805008448c72806008448c72807008448c72808008448c72809008448c7280a008448c7280b008448c7280c008448c7280d008448c7280e008448c7280f008448c72810008448c72811008448c72812008448c72813008448c72814008448c72815008448c72816008448c72817008448c72818008448c72819008448c7281a008448c7281b008448c7281c008448c7281d008448c7281e008448c7281f008448c72820008448c72821008448c72822008448c728230000"_hex_u8, {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36}); + TestOptimalLinearization("81c62aebef0200823580816a01819771dba4680280d371c4eb600381ac0ee3960604854080ae0c05845081ce140505823580a59b260605857c82bb400705824180e86008058a4884bc36090582428188380a05833182d3140b058235808f93460a05860881fc300b05832480c92c0c058332818f7a0c05860082b74c0d05844482c1160e058235ed82480f058545828578100583368186741105854c829a121205823980f8361205823981906e13058235809892121405845181b2001505833180f3481605823a8188141705860482b12c1921857c81f5401d00847c82a7201b038b7e84bf581c03824180ef6a1c04875382d1161f02826581ce621e04875385b93a2300854d83c1702400833e81ce202203823681bf182402823581bf182403823581bf182503823681bf182702823681bf182a00823681c75a270484448394622c00823581c75a2d00823981eb302e008a4484cd682533860482e96c2831824181e6282534845182fa5430012797518b902c310028833281b9381930845181dc44300018ad5688bd082e1b857c82dc2e075f823982ac58045c9b698c944e3500021d00"_hex_u8, {28, 32, 0, 2, 10, 13, 17, 20, 24, 59, 11, 57, 58, 56, 48, 52, 53, 51, 54, 55, 14, 47, 49, 23, 31, 36, 6, 50, 29, 43, 45, 12, 15, 16, 3, 9, 4, 34, 35, 5, 7, 8, 22, 27, 21, 41, 25, 26, 1, 30, 33, 44, 18, 46, 42, 19, 37, 38, 39}); + TestOptimalLinearization("8368aa5e008368aa5e018368aa5e028368aa5e038368aa5e0483689726058368aa5e05058368aa5e05058368aa5e05058368aa5e05058368aa5e05058368aa5e05058368972608038368aa5e010b854ea024080005a35780b638020ba35780b638010e83679708010d83679708020d83679708030d83679708040d83679708050d83679708060d83679708070d83679708080d83679708090d836797080a0d836797080b0d836797080c0d836797080d0d836797080e0d854eba7414001c836797080f1d83679708101d83679708111d83679708121d83679708131d83679708141d83679708151d83679708161d83679708171d83679708181d83679708191d836797081a1d836797081b1d836797081c1d836797081d1d836797081e1d836797081f1d83679708201d83679708211d8734cb0a2a0000308734cf280013112600"_hex_u8, {0, 1, 2, 3, 4, 5, 7, 8, 9, 10, 11, 6, 12, 13, 14, 15, 37, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52}); + TestOptimalLinearization("8361ee3400877f80d86401877e80d864028362ee3403877e80d86404877e80d86405877e80d864068362ee34078341e5640707877e80d86408078362ee3408078362ee340807877f80d86408078346e56409078361ee3409078361ee340907877f80f97608078342e56409078361ee340b068361ee340918877e80f51809178346e5640a178360f80c0a168342e5640b168362ee340b158361f80c0a148341e5640b148361fa420b138342e5640c138361fa420a118341e5640b118343e5640b2c8361fa420c2c8361fa420a288341ee5c0b288361fa420a268342e5640b268361fa420b238343ee5c0c23877e80f5180b218343f07a0c21877f80f5180b1c8343f07a0c1c8341f07a0a42877e80f5180b42877f80f5180b3b8341f07a0c3b877e80f5180b378342f07a0c37877f80f5180b338341f07a0c33877f819a421e0a2d877f819a420a1511877f819b2c031921877e819a42061121877e819a42090c3b877e819a420b0737877e819a4203141600"_hex_u8, {31, 47, 8, 0, 32, 33, 34, 35, 51, 52, 53, 9, 10, 48, 49, 1, 12, 56, 50, 54, 11, 39, 57, 2, 13, 40, 3, 5, 7, 41, 42, 43, 14, 15, 16, 17, 22, 23, 24, 25, 26, 28, 30, 45, 46, 4, 21, 6, 18, 36, 27, 44, 55, 19, 37, 38, 20, 29}); + TestOptimalLinearization("80de1a89c02e0080dd1c8aac460180d10789b70202b04282ee2803854da96204833da30005ae0e82d6200682429268078608ac7408833e973a09b4558397700a823589e10e0a0a8331b54c0b0a8335a0000c0a823588ec180c0a8544ac400d0a8242bd000d0a8235899b7e0e0a8546ac500f0a8544ac5011098242974e12098545d03a110a8331a42215058241974015068545d35c140883319d5017068578b37c130a8541d3261408f43185ba60120a82429b001607833282b6161a048235ac5a140a8336b87219068331b54c14288f1c81a34020001a8751bb1e2000178540ac341f001483359d6611228241cc781024833db67c101a8b708099280d1dbf3a85a62a2301021483319d4a0634833d9e1e0633dd3884c704230000108a58d654120f0a9e65829c580438880ff5100010208474e9700030894880bd1002013200"_hex_u8, {16, 45, 17, 24, 29, 9, 11, 10, 20, 5, 6, 0, 1, 8, 21, 28, 2, 4, 31, 49, 37, 25, 42, 32, 44, 46, 47, 34, 33, 35, 36, 43, 38, 39, 40, 41, 48, 3, 15, 30, 14, 27, 13, 22, 23, 12, 7, 18, 19, 26}); + TestOptimalLinearization("81903fc9ee3800819170cfe6520180d334bef35002819540d0d4480380da6ebdd94a0482359094100405823580a7120504823589bd760504847c819d100504823585f11c060482358d8d6a0604823589c62e0604823580b5520704a51586dd5008000000000000"_hex_u8, {8, 9, 1, 0, 2, 10, 11, 12, 5, 7, 6, 3, 4, 13}); + TestOptimalLinearization("808963829f2c0083638d2c000183638d2c010083638d2c020083638d2c030083638d2c040083638d2c050083638d2c060083638d2c070083638d2c080083638d2c090083638d2c0a0083638d2c0b0083638d2c0c0083638d2c0d0083638d2c0e0083638d2c0f0083638d2c100083638d2c110083638d2c120083638d2c130083638d2c140083638d2c150083638d2c160083638d2c170083638d2c180083638d2c190083638d2c1a0083638d2c1b0083638d2c1c0083638d2c1d0083638d2c1e0083638d2c1f0083638d2c200083638d2c210083638d2c220000"_hex_u8, {1, 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35}); + TestOptimalLinearization("8d29889718008368809064018368809064028d1386db10020292618bd5080302846380ac380301846380ac38030283688090640307854e80c6580500038360b8540403824182812a0503844682b6300603846380ac38040e8368809064050e8368809064050b846380ac38060a842ebf400609846380ac38031683688090640415846380ac380410846380ac38011a854e80c65802030b846380ac3800108368809064010e846280ac38000f8368809064010d846280ac38000e8368809064010e846380ac38000f00"_hex_u8, {0, 6, 23, 24, 1, 2, 4, 7, 9, 10, 11, 12, 17, 21, 25, 27, 22, 26, 3, 5, 8, 13, 14, 15, 16, 18, 28, 19, 20}); + TestOptimalLinearization("81bd6f8dc370008544a9200180df1588f04e028541ac340380c97c88b0240480e74989ca6c0583359a38068608d7240606854ec40a070687128091760806941381c52009068608d7240a06854de8200b05a32081e9680c058445c4200d058335ad300e05823580b40e0f05875d80856810058450809a380f068578d60e10068545d03a11068546b63212068a54808b20130682419c7214068474b93e15068235a26216068608d7241706833ead6c1806823580840a19068242cd221a068754c4081b06847480971a19068235c5281a068a58809c641b068474d2101c068239c2041d06854cd11e1e06823aa16e1f06ab7282a6702006823580887621068608a22825028540af5224048500e23425048336c0502604823abf2627048235fa3a2804896a80984e2904823997162a048803bd7a2b04823a97082c0483329d4a2d048332b1343002857cd64028388d7c818d0033002d8500ca0022328452ec581d36845180804835011a8545b9541a368546c658242dac1f82811c3702178450af18360210a70de536270e10854dee6c2c0c0400"_hex_u8, {7, 0, 13, 3, 8, 9, 14, 4, 11, 1, 5, 6, 12, 2, 10, 15, 28, 16, 30, 29, 17, 22, 26, 18, 20, 62, 24, 25, 27, 23, 21, 19, 33, 31, 32, 34, 36, 37, 47, 38, 39, 42, 41, 40, 43, 44, 45, 46, 35, 55, 54, 61, 52, 53, 56, 51, 57, 58, 59, 60, 48, 49, 50}); + TestOptimalLinearization("c554baaa4600835c82fa220000835c82fa220100835c82fa220200835c82fa220300835c82fa220400835c82fa220500835c82fa220600835c82fa220700835c82fa220800835c82fa220900835c82fa220a0000"_hex_u8, {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}); + TestOptimalLinearization("8184258aa316008185018287740180f14981ea6c028183288285600381a93a82c0180481831082a64005818a4182b2460681884983ae0a0781911684fd2208857cc81608088950904409088a4480d3240a08823590e0460a0882358fba2e0a08823590d1380a08823593963a0a08823590ed140908823590ae680b07823584640b08823a9f540d078235846e100585159a640f078541886014038478b41015038a54f370120782368a7a1604823588be08190282358fde161308854188601408823ab9661a03823a85101a048544c0141906844487281c048332aa561b068239a6181b078944e9201b0882358ee5281b088540bf6c1c08850088001d088c5f934a1e088445be0e2601833587662206854ce25a26038236856c22088541c30c2a018332875e0d2a8444c554250408875dd152121716833d8776023080970e80e35a013a9c6d81aa082b0000000000002400"_hex_u8, {0, 25, 3, 1, 8, 9, 48, 6, 7, 30, 39, 40, 44, 4, 5, 46, 50, 13, 15, 37, 26, 27, 38, 10, 11, 12, 16, 23, 14, 32, 41, 34, 18, 22, 28, 29, 20, 24, 49, 47, 35, 45, 31, 19, 17, 2, 36, 33, 42, 21, 43}); + TestOptimalLinearization("836880ed0e00d724a0e46400008430818630000084308186300100842c81846c02008430818630030084308186300400842c81846c0500842c81846c060084308186300700842c81846c080084308186300900842c81846c0a0084308186300b0084308186300c0084308186300d00842c81846c0e00842c81846c0f0084308186301000842c81846c11008430818630120000"_hex_u8, {0, 1, 4, 7, 8, 10, 12, 16, 17, 19, 2, 3, 5, 6, 9, 11, 13, 14, 15, 18, 20}); + TestOptimalLinearization("d02a82c24800fe6b84ff6001de7983ff08028235930202028578e04803028336915204028a48809e3405028474829172060285409a3807028474e30c08028a48809e34090283128d3c0a0283118d3c0b028608e1700c028948fd600d02857ce4060e028a5880aa140e028542b5700f028a4480a70e100282359f0412018600e44012028600e8001302b62180aa301402854182ad48150282368f0216028a4cef3417028a50d65418028500ee761a018600e4401a028236a3041b0286538292241d018578eb021e01823684fe6c1e028235a9061e028478f1241f02857cee4020028474dd4021028236ad0623018235a50423028241f41824028235a104250282418f0225238a5480a83c2800188235900a1e20824181834e181e82359f3e270f8a5080b9002b01078241a9060d2700"_hex_u8, {0, 5, 33, 29, 7, 35, 20, 32, 14, 15, 36, 25, 23, 16, 19, 18, 21, 30, 2, 12, 4, 9, 44, 13, 31, 37, 46, 41, 43, 42, 39, 38, 40, 45, 47, 27, 17, 28, 3, 34, 1, 26, 8, 6, 11, 22, 10, 24}); + TestOptimalLinearization("80896681da040083668b04000183668b04010083668b04020083668b04030083668b04040083668b04050083668b04060083668b04070083668b04080083668b04090083668b040a0083668b040b0083668b040c0083668b040d0083668b040e0083668b040f0083668b04100083668b04110083668b04120083668b04130083668b04140083668b04150083668b04160083668b04170083668b04180083668b04190083668b041a0083668b041b0083668b041c0083668b041d0083668b041e0083668b041f0083668b04200083668b04210083668b04220083668b04230083668b04240083668b04250083668b04260083668b04270083668b04280083668b04290083668b042a0083668b042b0000"_hex_u8, {1, 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44}); + TestOptimalLinearization("80ea55a1fc3c0080e47da4dc2c0180e159a1c3340280e411a4ca500380d35ba1f20c04823586f77404048a5080b00405048265994a0604823a994a07048242c90a08048500e91a0904823680830e0904850081884e0a0482358397480b048474d8080c0485208194460d048542bf6c0e04854dc40a0f048239c92010048335ad181203823585e33a1104853f80871812048474e80613048236e47a1304823582a2261404823582894414048241c86a1504854cc40a17038658d0301704854dc0641804865fc4601c00138546c3361c0109833eb00a041c8452ba141c0004875c80c2541e0002833ead6c032900"_hex_u8, {7, 10, 13, 9, 8, 18, 19, 0, 1, 24, 26, 25, 27, 28, 35, 16, 5, 29, 20, 21, 6, 2, 12, 30, 31, 32, 33, 15, 17, 22, 23, 34, 14, 11, 4, 3}); + TestOptimalLinearization("83698158008570832e0183698158028361831403875387440483698158058369815806b95d82d2480785018222088369815809836981580a836981580b836981580c8669831a0d836981580e836198220f8369815810860b843211836981581111843083221111bf69a814111183698158121184308336121183698158101188018362101183698158130a836981580e108430883c0b1183698158092b8339836c092a83698158082983698158082883698158082583698158061f83698158061c83698158091883698158073b83698158073983698158052983698158042383698158042183698158044687538744052d83698158042d83698158042883698158034d83698158012a836981580329836981580252823d880c022b83698158013d83698158003e83698158003d857c8968050a1f823d8400013eb623c2281104000004010500000000000019a63281c2600b0100010203050000000f00"_hex_u8, {23, 43, 44, 49, 0, 1, 2, 3, 37, 4, 19, 20, 21, 22, 28, 31, 34, 38, 39, 42, 45, 46, 47, 48, 41, 50, 51, 53, 18, 40, 52, 54, 15, 16, 7, 8, 9, 10, 11, 13, 14, 17, 26, 27, 29, 25, 24, 30, 5, 6, 32, 33, 35, 36, 12, 55, 56}); + TestOptimalLinearization("836280c06000836180c06001836280c06002834280b1600202836180c0600302834280b1600302836180c0600402834280b1600402836280c0600502877e81fc200509833a80b1600509836280c0600609877f81fc200608834180b1600608877e81fc200607836280c0600607834180b1600707836180c0600715834280b1600614836280c0600611836180c060050f834380b160050d834180b1600420834380b1600318834280b1600315836180c0600510877f81fc200327880281f96010030d836280c060012b834280b160002c836180c060012c880281fc2006070e834280b160012e836280c060022a877f81fc200a0913833b80b160012d877e81fc2002022a877f81fc2009050e877e81fc2001022c877f81fc20040f0a877e81fc2000110b877f81fc20020f0b877e81f96006021100"_hex_u8, {0, 1, 2, 3, 4, 5, 18, 19, 20, 27, 28, 29, 10, 21, 30, 6, 8, 12, 14, 22, 32, 33, 11, 26, 15, 23, 35, 7, 16, 9, 17, 38, 13, 31, 34, 41, 24, 25, 37, 39, 36, 40, 42}); + TestOptimalLinearization("836880bf4000834c80b6600000836880bf400100834c80b6600001836880bf400101834c80b6600002836880bf400102834c80b6600003836880bf400103834c80b6600004836880bf400104834c80b6600005836880bf400105834c80b6600006836880bf400106834c80b6600007836880bf400107834c80b6600008836881b768010800"_hex_u8, {0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 1, 3, 5, 7, 9, 11, 13, 15, 17}); + TestOptimalLinearization("8369817400885084460183698174028369817403842482760485028244058501824406836981740783698174088550827609866883460a836981740b836981740c850282440d836981740e836981740f8550827610836983261183698326128550846613836983261483698326158501841c168501841c1783698326188550846619836981741a836983261b836983261c836983261d842486681e836983261f83698326208501841c2185508276228550827647850182442483698174258550827626836981742783698174288369817429836981742a866783462b836981742c836981742d836981742e836981742e2f956f9220152f873786240e2f8667855c142a8b0589240f23823d897c0453bc50d70c06000000000000000000000024bf66db78061e00000000000000000000000000000035c30085961a0200020b000000000000000000000000000000003500"_hex_u8, {35, 21, 22, 24, 25, 28, 32, 33, 34, 36, 37, 23, 29, 26, 27, 38, 0, 1, 17, 30, 31, 39, 43, 56, 19, 45, 47, 48, 49, 50, 52, 53, 54, 46, 44, 51, 55, 6, 4, 5, 9, 10, 13, 14, 16, 18, 11, 20, 8, 7, 15, 12, 3, 2, 40, 41}); + TestOptimalLinearization("cc1b8ae36800d6628bd74401912d81d342028368d406038e54819144048f7481a73405af7687b42806d35e8aa12c078416ab0c088f4781d31609a42e85905a0909b53087da7c07098459e30a0809cc4789cd7e0709912881db4405098422de500509a84b8693220e000d901e828d56050f823cce0e030f9017828c2201158608809b340807000d901e81d8420116925282b97c080600020a901c81d8420117901f81d8420012ca088ab75202010102020200"_hex_u8, {12, 5, 6, 14, 15, 22, 16, 17, 25, 0, 1, 2, 3, 4, 8, 9, 10, 11, 13, 23, 18, 19, 20, 21, 24, 7}); + TestOptimalLinearization("8530af0600853daf60018930cd0602893abe00038638b70204862db62805853da600068a39e134078531af060707853caf600707853ca60007078531af0607078530af0606078530a53808068332b77408078540e6600c04883cc62009078500dc3e0c058500dc3e0a078312bf5e0b07853caf600b198531af060b168a4cd6180a1682359d5e09148241a0200b11853caf6008138239be4c09138541bf6c0b0e853daf60072b8745bf1c06258530af06081d8751d50209148f4bfb581200188531af0604278530b53a03228500dc3e05208638ab68032d8332b774042c8531af0604298a4880a930032b853db940051f8c33e3640b10248931cd0605348235a44806348530b53a052a8570f4340423853ca600044387548091640430853db9400328937081fa741410002e8835c564033c8a4c80a9300b12168236b366012a8c3be4200a0e23894480997c021c138e4bf4180102308f1c80cc6e06020832853ca60001338654f55602298534a55001338824ce14003f853ca600003f00"_hex_u8, {51, 53, 52, 16, 49, 10, 11, 12, 13, 48, 36, 50, 54, 6, 29, 0, 1, 2, 3, 4, 5, 7, 8, 9, 31, 44, 57, 60, 59, 56, 17, 28, 18, 32, 14, 19, 21, 27, 15, 30, 61, 22, 25, 24, 23, 41, 20, 37, 38, 47, 39, 40, 42, 55, 26, 33, 45, 58, 43, 46, 34, 35}); + TestOptimalLinearization("80884d94bf40008349db4000018349db4001008349db4002008349db4003008349db4004008349db4005008349db4006008349db4007008349db4008008349db4009008349db400a008349db400b008349db400c008349db400d008349db400e008349db400f008349db4010008349db4011008349db4012008349db4013008349db4014008349db4015008349db4016008349db4017008349db4018008349db4019008349db401a008349db401b008349db401c008349db401d008349db401e008349db401f008349db4020008349db4021008349db4022008349db4023008349db4024008349db4025008349db4026008349db4027008349db4028008349db4029008349db402a008349db402b008349db402c008349db402d008349db402e008349db402f0000"_hex_u8, {1, 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48}); + TestOptimalLinearization("80cc00829900008449c452018336c318028335b4200380c95c86c57004ce3488a30c0580b63281ed680683358c1a078477da46088336b37c0988728092340a8540955c0b9f0a82831c0c8474c2760c0c82359094240d0c8335b2160e0c8239af7e0f0c823aad50100c9738c840110c8478c3520e0c823581db200f0c82358ae40e100c847cbb000f0c8478cf74100c8331a006110c8311af5c120c82358dd418130c8239ab58140c8331b97c1708854d926018088478c32419088600cf401e048621b8701f048235b13a1c088336bc4a160c8242b01c1e048335b216142d8331b97c08268474d14c131b967e81f164040a0a000009bd6580a1061f00000000000000000f00"_hex_u8, {24, 9, 15, 35, 11, 14, 13, 33, 40, 26, 27, 0, 2, 4, 6, 8, 38, 34, 36, 37, 16, 21, 18, 39, 22, 10, 20, 3, 5, 12, 1, 30, 31, 17, 32, 19, 7, 29, 28, 23, 25}); + TestOptimalLinearization("cf0884cf6c008324a54400008324a54401008324a54402008324a54403008324a54404008324a54405008324a54406008324a54407008324a54408008324a54409008324a5440a008324a5440b008324a5440c008324a5440d008324a5440e0000"_hex_u8, {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}); + TestOptimalLinearization("8474ad70008474ad70018470ad70028470ad70038470ad70048470ad70058470ad70068474ad70078474ad70088470ad70098474ad700a8474ad700b8474ad700c8470ad700d8474ad700e8474ad700fb83285d734000000000000000000000000000000000f00"_hex_u8, {3, 4, 5, 6, 7, 10, 14, 0, 2, 8, 9, 11, 12, 13, 15, 16, 1}); + TestOptimalLinearization("a408f07c00832c8c320000832c8c320100832c8c320200832c8c320300832c8c320400832c8c320500832c8c320600832c8c320700832c8c320800832c8c32090083308c3e0a0083308c3e0b0083308c3e0c0083308c3e0d00832f8c3a0e00832f8c3a0f00832f8c3a1000832f8c3a1100832f8c3a1200832d8c341300832d8c341400832d8c341500832d8c34160000"_hex_u8, {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 20, 21, 22, 23, 15, 16, 17, 18, 19}); + TestOptimalLinearization("8362861c00da64e1740000832a83460000832a83460100832e834a02008331834e0300832a83460400832a83460500832a83460600832a83460700832a83460800832a83460900832a83460a00832a83460b00832a83460c00832a83460d0000"_hex_u8, {0, 1, 5, 2, 3, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 4}); + TestOptimalLinearization("80df4cacb754009e3d87e13a0180f36aac8350028541808e5803833180867004833180ce0a05971285db6206ab6d8bbe0407854180f21608841280c278099a2e86ce3c0a83328086700ba81f8abc700c857c80ef360d860080fb000e8331809e140f857881922210ad498bfa16118331808e1a1281c806d98a341380d468ad813a148235a4fa741415824180a40015148239d05c1614823ad22017148236d1101714847480bc561714823980804018148235ace32819148331e7681a138236e35c1d11833580d5681e11854480c66a19148236f9301614833280a23e1c0d8331808612181285788187681514857c81a01a1414846681882e1414823a809620151482359ec46414148335f12e151482359392721514854480a5161614847c80f9502b008241e252191382358082122b02833df27e1130857c818b260b338578818b260b31854d80aa041d1105857c819222013d857881aa5403358a7581d40e3100000029857c81aa540133c92091aa5e2a0000000000000000011e823580a6480035a10988bb460103010b0e000000000d00"_hex_u8, {17, 1, 0, 15, 2, 44, 45, 7, 10, 54, 36, 37, 32, 33, 34, 48, 55, 38, 39, 50, 51, 57, 22, 9, 21, 28, 40, 41, 42, 35, 23, 24, 5, 18, 20, 26, 31, 43, 16, 25, 27, 49, 47, 8, 30, 19, 14, 56, 11, 12, 46, 53, 52, 13, 29, 4, 6, 3}); + TestOptimalLinearization("846ea73e00846ebc68018540ab6602846ebc68038540ab6604846ebc6805846ea73e06846ebc68078540c33208846ebc6809846ea73e0a8540ab660b8540ab660c8517a9520a0c8517a9520a098517a952030c8540ab660e000e8540ab660e000d8540ab660d000d8540ab660e030a8540c3320d000d8540ab660e000d8540c3320d000c8540ab660e000c8540ab660b02098540ab660e00098540ab660a020d8540ab6601178540c3320e010a8540ab66021b8517c00c01198540ab6609071b8540ab660907178540ab660d02198540ab6609090d8540ab660e021b8540ab660c041b8540ab660a00178540ab660a04138540c3320702168540ab660605178540ab6604031b8540ab660411108540ab6601228540ab6605031a8540ab66020b168540ab66050e108653b72a0a00032800"_hex_u8, {1, 6, 10, 16, 25, 17, 18, 11, 12, 3, 4, 27, 45, 46, 13, 14, 47, 5, 7, 8, 19, 21, 23, 24, 0, 26, 15, 28, 2, 9, 20, 22, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44}); + TestOptimalLinearization("836880d74800836880d74801836880d74802836880d74803834c80cf100303836880d7480403834c80cf100403836880d7480503834c80cf100503836880d7480603836880d7480603834c80cf100703834c80cf10060d836880d748070d834c80cf10060c836880d748070c834c80cf10060b836880d748070b834c80cf10070a834c80cf100519836880d7480619836880d7480516834c80cf100616836880d7480513834c80cf100613834c80cf100423836880d7480523834c80cf10051e836880d748061e834c80cf100519836880d7480619834c80cf10042c836880d748052c834c80cf100426836880d7480526834c80cf10041f834c80cf100334834c80cf10022b887685bb3e0301010b0300"_hex_u8, {0, 2, 4, 6, 8, 10, 12, 14, 16, 17, 19, 21, 24, 26, 28, 29, 31, 34, 35, 38, 1, 3, 5, 7, 9, 11, 13, 15, 18, 20, 22, 23, 25, 27, 30, 32, 33, 36, 37}); + TestOptimalLinearization("808934829e280083348c28000183348c28010083348c28020083348c28030083348c28040083348c28050083348c28060083348c28070083348c28080083348c28090083348c280a0083348c280b0083348c280c0083348c280d0083348c280e0083348c280f0083348c28100083348c28110083348c28120083348c28130083348c28140083348c28150083348c28160083348c28170083348c28180083348c28190083348c281a0083348c281b0083348c281c0083348c281d0083348c281e0083348c281f0083348c28200083348c28210083348c28220083348c28230083348c28240083348c28250083348c28260083348c28270083348c28280083348c28290083348c282a0000"_hex_u8, {1, 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43}); + TestOptimalLinearization("80af1a838c0a0080b37b82af76018335854e028335a64e03867cb2760483358a0c0580cd6485e13206854c8f3a0606823586e37207068241894608068750901a0906857cf2400a06823aab020b06824194060c068541bc500d068608f3440e068241a2000e06854ebd420f06823588b41610068500e13e11068241a2501206894480c21413068500905a1406854d8f3a150683368766160683358a0c1306823a983a1306823586bd7e140685458f261506833da17616068242a0341321854dc0641d000a83318a02061d854dc064120d8751901a0124b524808a58091200000000000200"_hex_u8, {11, 14, 17, 15, 16, 12, 13, 0, 2, 5, 10, 7, 21, 9, 35, 23, 29, 31, 34, 30, 24, 8, 4, 6, 3, 18, 25, 26, 27, 1, 22, 33, 19, 32, 28, 20}); + TestOptimalLinearization("818241dbac3c0081c70c809fe6240180d740e79b0c0280eb5af7b4420380bf15cec96a0480fa208081cf4c0580ee2bf89d3a06950d8a8d7e0780c557e3bb7c0881866980839b52098235829f6a090982359fbf3209098335818f5a0a098331818d620b09823596fa1e0b09847882bc280c09823580e97e0d09845081de320e09823592c7020e09847482d4420f0985428291041306824281ec6c1208847882955c12098235a1b3181209863083f66a1309823580fa20130982358fec3c1409823593a460140984788298581608823680dc761609824180d87c1807863d83f32e160982358fc3761709823596ca261709857c82de401809823a80805019098239cb261b088948ce1c1b09a04c90d5682400228449829160220015866083b07022010c845181fa581f000b875183ee50210304857c82f460082186618381462800001e896d849d302500001200"_hex_u8, {7, 8, 17, 19, 20, 21, 9, 12, 13, 14, 2, 3, 37, 38, 26, 27, 34, 36, 35, 23, 25, 24, 33, 22, 44, 39, 45, 28, 10, 18, 40, 15, 29, 30, 11, 31, 5, 6, 32, 0, 1, 4, 16, 41, 42, 43}); + TestOptimalLinearization("a91cb4e81c00fc20809ebc6801a454aef86e02ad6cbad74c03e044fba04e04c020d2950605a004a9893e06a004a9893e07a454aef86e089b38a39a1009a928b4e81c0a8d4c91cc040b8d4c91cc040c81940681dfa368000000000000000000000000000000"_hex_u8, {0, 5, 11, 12, 3, 4, 6, 7, 2, 8, 9, 1, 10, 13}); + TestOptimalLinearization("836181ba1c0088318bdc580000a34a97cd280000a34a97cd280100a34a97cd280200a34a97cd280300832a82965e0303832a82965e0403832a82965e0503832a82965e0603832a82965e0703832a82965e0803832a82965e0903832a82965e0a03832a82965e0b03832a82965e0c03832a82965e0d03832a82965e0e03832a82965e0f03832a82965e1003832a82965e1103832a82965e1203832a82965e1303832a82965e1403832a82965e1503832a82965e1603832a82965e1703832a82965e1803832a82965e1903832a82965e1a03832a82965e1902832a82965e1b01832a82965e1c01832a82965e1d01832a82965e1d02832a82965e1f01832a82965e1f02832a82965e2002832a82965e2201832a82965e2301832a82965e2302832a82965e2402832a82965e2502832a82965e2701832a82965e2801832a82965e2901832a82965e2a01832a82965e2a02832a82965e2b02832a82965e2d01832a82965e2d02832a82965e2f01832a82965e300100"_hex_u8, {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 31, 32, 33, 35, 38, 39, 43, 44, 45, 46, 49, 51, 52, 28, 30, 34, 36, 37, 40, 41, 42, 47, 48, 50, 29}); + TestOptimalLinearization("921a84f92a008312809d6801841280c870028b7082891803945985e91004997e87ad7c0580b815ada40006941185c61807974d86cf62089f0a88f80209926d85932e0a963686a0560b945a85dc400c8d2183b53c0d9c5288972a0e9b4e87ee380f943585d12c108e1183d818119625869b5a128f3184896213911a84d154149305859a6415914284de0816980986e22e17920d84f54e18841280c2061818875c82817a1918854d818c5c1518823583bf4c1518861c818d101717857080d7481718866081cc2017188235fe2c1618866281d13e1518847880e9441518857880eb781318894c82b7781218850df5601018847c80ed601018854d80e51e0f18847480ed601018854280a71e1018850081a50002298d7f84983828000025dd44a5ec3425000025823980ac38014e866081f670022726ac7cc3fd5016000000000000000000000000000000000001042900"_hex_u8, {28, 33, 36, 46, 23, 39, 18, 32, 35, 20, 42, 41, 37, 0, 26, 24, 11, 30, 29, 21, 6, 2, 25, 4, 3, 7, 8, 19, 34, 43, 44, 12, 10, 13, 15, 14, 45, 40, 27, 1, 16, 5, 9, 22, 31, 17, 47, 38}); + TestOptimalLinearization("836880832c00850d80a738000000"_hex_u8, {0, 1}); + TestOptimalLinearization("836883680084428f4c01836883680284428f4c03836883680483688368058368836806836883680783688368088368836809836883680a836883680b80a70f80a7100b0b809b7c809b7c0a0a809947809948090b809b3e809b40090b80a12b80a12c090b809a2d809a30090b809c0b809c0c090b809554809554090b809913809914090b809b53809b54090b854e80aa4c091f854e80a13a091c872d9804140111854e80a76a0a1b854e80a44e0a1a854e80a9000a19854e80a1440a18854e80a44a0a17854e809d0a0a16854e80a3140a15854e80a13c0a1484418f4c082e867a80c3560628854e8188060c131f854e81887c0c121d84428f4c033184428f4c0034854e80ea2a0d002c84418f4c012a867a80bc3407062b84418f4c012b84418f4c002984428f4c002684428f4c0023854e80a45003072284428f4c0123886080be340a020427854e80a300050620854ed83c05051d886080be7402090524854ed84600092900"_hex_u8, {6, 5, 7, 8, 9, 3, 0, 1, 2, 4, 10, 12, 13, 14, 15, 11, 20, 21, 34, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 35, 36, 41, 46, 51, 52, 16, 17, 18, 19, 37, 38, 39, 40, 42, 43, 44, 45, 47, 48, 49, 50}); + TestOptimalLinearization("8a4481f65e008f7783dc7c00008f7783c70801008f6f83c70801008f7083c7080100008f7783bf620100008f7783bf620100008f7783bf620100008f7783c70801019b1686e862000200"_hex_u8, {0, 1, 3, 2, 4, 6, 8, 9, 5, 7}); + TestOptimalLinearization("dd5096a94c00db479a8f2201de64999944028236809310020285008082080302847c8083020402857c80830205028a5480d9140602847080f950070285008083020802857cfc38090283318c9b520a02823686d3220a02824187b83c0b02823680ad120c028236e65c0d028478fd180e028239c5640f028a5480d91410028a4880d60811028544e5301202854588ba341302847c8082641402823a87f5101402823687ab7e1502823680a1121602823580ad121702823680a7121802833e80c05e1902823ae9161a028241e1381b02850080966c1c0284788083361d028500fe641e02857c8083021f028a4480d9142002847cee0021028578ff7622028a4480d32423028500eb0024028a4c80cf582502833dc52826028a4c80d914280016824185df5e1128823a80ad1211288a4480cf582a000100"_hex_u8, {10, 12, 11, 21, 23, 24, 25, 26, 27, 28, 13, 29, 30, 0, 9, 1, 31, 6, 32, 14, 33, 34, 35, 3, 22, 7, 2, 36, 15, 16, 4, 37, 38, 20, 5, 17, 18, 39, 40, 41, 45, 42, 8, 43, 44, 19}); + TestOptimalLinearization("e05381ab28008756a16001904deb4a02a2608a900003971e81fb4604f32981e44005f179829b2606a51f80ea6a07e15182bc4208e55583b34e099029ed540a8d7adb1c0b882cc9200c8d29d72e0d9235f6600ef77284982a0f823581ea3c0f0f8235975c100b8600e1000c0f823582ab740d0f8265900c0e0f823581ed660e0f964181f340110d9838829b241609823a80cc6a100f857ceb40100f823580da10110f8474829172120f8235b94c130f8235fb58130f82419504160c82358c76140e82428c76150e85429632190b823980a002130f854480b348140f823580a61a140f80c7638487361e000418809e1a83c44421000000002080cf6484a24207130000000e9121d5361800000003020500"_hex_u8, {4, 5, 15, 35, 36, 37, 17, 18, 19, 22, 21, 23, 20, 0, 1, 16, 33, 7, 8, 10, 9, 38, 39, 12, 13, 24, 25, 26, 27, 34, 3, 28, 40, 11, 29, 2, 30, 6, 31, 32, 14}); + TestOptimalLinearization("80d25b87e93a0081fc0b8ef06a01d96182e34002d51082ca6603c36081ee3c04e02a83865e05d43882c72606c24581e7500780a61285fb1a08bc3f81c73409d87582df160ac74d8282560bce0f82a5480c808b3084ec3a0dc57681f96a0e80852c84cc0a0fce1482a54810be2b81d12011833e9c0011118241956e121183158e5013118450a3501311857c80b80414118242956e15118416ad3e1211857ced5e131182419b20141182399c3e1411847480971a1511880fde3414118544bc7614118331977015118336aa7e1511847cd30015118608f34416118449f54c1611854dc40a17118241a2141711844ab62c17118335993218118241921419118a5080b574181183369b4c1911847ca3001a11954880fc6026058451a540270583158e50193d8474808526183c8451a3502800218331aa56123483168e50035983168358005caa17c280442200000000000000000000000000000000002d00"_hex_u8, {15, 41, 42, 36, 37, 38, 20, 22, 27, 28, 29, 50, 31, 32, 16, 18, 51, 33, 35, 34, 0, 23, 39, 40, 14, 13, 46, 47, 25, 26, 45, 8, 7, 10, 11, 17, 21, 19, 52, 2, 9, 12, 24, 1, 48, 49, 43, 30, 44, 3, 4, 5, 6}); // Hard clusters (according to various metrics) in synthetically generated clusters, with 26-64 transactions. - TestOptimalLinearization("826db830008414a23c01744d028723d67e0103845cb0480201846ca1060202802d8b0e030104852dc545040104800e825f040283548424000f830aba39010a8241991402068612d67503030d8360b66301108712eb58070003843b905805040d8449865e05000b8503cd1908040003825ca40b03060204844b8a3c03030313852e8456030404000c834c9d1107000103000b8717b2590a00000200000b8035901106030003000f810c8a1c0a00000003000f862ea7130608000b816aa87706040400188112905b05070a8327bb040d02000000000d844cce410a05010009807994720502040e803c84690a0202020000058061813301050520800e8d6f0906010000001c84288f45090204000100001f820aa37607020206000d8073857c0602091f8539c4120602020502001a8728c826050c01078364c673060c0106832da9030b02020300000000286c877903040a00258466be7b050606000020840e9b7105010a23815f9321080300040002000000867fdf300500000a02002285168b50060008000100010123841ac7210704000200000101001c834d816706020302020000000022845ace070505000000010000000f81419e650207000002002c844eb3520b0000000100000000001582129f1c0b000000020000000008807b98060a0200020000000000038011825908010102000000000100001580378e3006040200000000038561ac27030103020e82459c170002000202000b8336a9420203000000000000000f00"_hex_v_u8, {{3672, 493}, {9871, 2079}, {7901, 1719}, {3172, 732}, {1434, 591}, {1470, 1295}, {734, 715}, {-3533, 9003}, {-3439, 2406}, {-1059, 680}, {-15211, 8262}, {-2491, 993}, {-1297, 351}, {-11899, 3148}, {-1868, 453}}); - TestOptimalLinearization("823f9b1b00864fa2680182328c07028017890c02038607d0770105864dd04a0205852f80020108801e8c6c0208840aac1c050006813f9b0e010e826b9340040006806b856006000969823108000000870bb1230403010c837cb754040502867f934c0600010983388872050100088549c578060001010f861b812304040109872daf3004050109841f8a3208010100000a86008b0d04000407824ea36902090015850f802d01081881068d7f0501000310862fab02000915827e961f0308000011855ac76f030405028668b31a0202061c8602a81b020700001e82029017010a8351af460105000009801b866601030300010e837aa96602030200010e8420af76020400000008850fb76701000201000014861fc37804000100001000"_hex_v_u8, {{9571, 3032}, {9352, 6065}, {1318, 1023}, {633, 568}, {729, 671}, {7060, 11184}, {-8300, 1641}}); - TestOptimalLinearization("8365c026008371c34b01841bc8160284789d30038141a3160486478906058645803806855f977d078175a27308831dab3e0986188b780a8031876b0b8539c1050c8708ea770d825b88020e82588c000f814d9f59108560de11118643c124128058856b13833da2251483229a35158723cc5116800e80241780108e5418807e9432198269a64c1a855cb10d1b82628d431c834cb73600000000000000000000000000000000000000000000000000000000001d8545a35601000000000000000000000000000000000000000000000000000000001c866bd03002000000000000000000000000000000000000000000000000000000001a8251a152030000000000000000000000000000000000000000000000000000000019847d8c2104000000000000000000000000000000000000000000000000000000001887129a26050000000000000000000000000000000000000000000000000000000017840b8517060000000000000000000000000000000000000000000000000000000015857c9c7f0700000000000000000000000000000000000000000000000000000000148608860d080000000000000000000000000000000000000000000000000000000013855d987a0900000000000000000000000000000000000000000000000000000000128461a33f0a00000000000000000000000000000000000000000000000000000000128701e97a0b0000000000000000000000000000000000000000000000000000000010820e84790c00000000000000000000000000000000000000000000000000000000108521d6290d00000000000000000000000000000000000000000000000000000000108406bd0e0e000000000000000000000000000000000000000000000000000000000d850e9f140f000000000000000000000000000000000000000000000000000000000b8424b46510000000000000000000000000000000000000000000000000000000000a830e9c6e110000000000000000000000000000000000000000000000000000000009850d894912000000000000000000000000000000000000000000000000000000000881308b0c1300000000000000000000000000000000000000000000000000000000058273a1581400000000000000000000000000000000000000000000000000000000048426cc27150000000000000000000000000000000000000000000000000000000002817f9964160000000000000000000000000000000000000000000000000000000001873ad510170000000000000000000000000000000000000000000000000000000001816f832a180000000000000000000000000000000000000000000000000000000001874aaf1c19000000000000000000000000000000000000000000000000000000000100"_hex_v_u8, {{2315, 321}, {4683, 667}, {1002, 144}, {4179, 613}, {1369, 254}, {2847, 541}, {2534, 489}, {4242, 963}, {1944, 760}, {832, 472}, {577, 475}, {828, 920}, {643, 967}, {82, 142}, {3527, 21301}, {-455, 904}, {-396, 651}, {-677, 781}, {-381, 398}, {-849, 765}, {-1920, 892}, {-2336, 737}, {-3443, 676}, {-5589, 801}, {-4948, 678}}); - TestOptimalLinearization("8741984d008704eb3f01815799390281319457038626a424048661dc1705861fbf1106814685750782448178088331af0c098525ae120a8662aa220b816d450c8210a2430d870e9a160e804692290f845690751081158744118029844312871ac2091381589435148520ad471580548441168512d313178422b948188647b82e198267a50f1a81479b4d1b815c8c291c8640a8031d851faa720000000000000000000000000000000000000000000000000000000000001d813587770100000000000000000000000000000000000000000000000000000000001d84268e170200000000000000000000000000000000000000000000000000000000001a815f99300300000000000000000000000000000000000000000000000000000000001783569c6c04000000000000000000000000000000000000000000000000000000000016850fa31c05000000000000000000000000000000000000000000000000000000000015833eac460600000000000000000000000000000000000000000000000000000000001081589c4e0700000000000000000000000000000000000000000000000000000000000c805395560800000000000000000000000000000000000000000000000000000000000b817a83730900000000000000000000000000000000000000000000000000000000000a807e8e530a00000000000000000000000000000000000000000000000000000000000a842ac5360b000000000000000000000000000000000000000000000000000000000009803388160c00000000000000000000000000000000000000000000000000000000000785069b4d0d000000000000000000000000000000000000000000000000000000000007831b9e0b0e000000000000000000000000000000000000000000000000000000000003803989220f0000000000000000000000000000000000000000000000000000000000038663ca511000000000000000000000000000000000000000000000000000000000000383789013110000000000000000000000000000000000000000000000000000000000028418907f1200000000000000000000000000000000000000000000000000000000000286178422130000000000000000000000000000000000000000000000000000000000028072935e140000000000000000000000000000000000000000000000000000000000018222825e1500000000000000000000000000000000000000000000000000000000000000"_hex_v_u8, {{3748, 674}, {3078, 561}, {3671, 967}, {3017, 805}, {2769, 994}, {2386, 934}, {546, 277}, {1739, 1038}, {188, 452}, {-35, 365}, {-443, 326}, {-27524, 18833}, {-1152, 664}, {-1098, 632}, {-572, 309}, {-1831, 774}, {-1990, 539}, {-1002, 254}, {-4841, 995}}); - TestOptimalLinearization("814e9f7400857edb66018043813402821fa96e038608bd4c048348bc2d05815ca33c06833387610780068b7408842ca841098059823d0a835382320b85418e4b0c84079d380d814b93520e83218a1a0f816b83491084088a4f11802e910512810a8e67138418c1541480408b2715845aaf6d1682529e5c000000000000000000000000000000000000000000000016837e88730100000000000000000000000000000000000000000000148733ce200200000000000000000000000000000000000000000000118279913c0300000000000000000000000000000000000000000000118276af0204000000000000000000000000000000000000000000000f80598c2405000000000000000000000000000000000000000000000f8734e31706000000000000000000000000000000000000000000000e804b803507000000000000000000000000000000000000000000000a85308b320800000000000000000000000000000000000000000000098418c039090000000000000000000000000000000000000000000008852898740a0000000000000000000000000000000000000000000006807596680b000000000000000000000000000000000000000000000585389e3e0c00000000000000000000000000000000000000000000058612cd260d00000000000000000000000000000000000000000000048338a41c0e000000000000000000000000000000000000000000000486068d430f0000000000000000000000000000000000000000000004806595121000000000000000000000000000000000000000000000038719de681100000000000000000000000000000000000000000000038301ab6912000000000000000000000000000000000000000000000380158b2b1300000000000000000000000000000000000000000000038138844b1400000000000000000000000000000000000000000000038465cb1615000000000000000000000000000000000000000000000386768e491600000000000000000000000000000000000000000000028072920f17000000000000000000000000000000000000000000000200"_hex_v_u8, {{2334, 348}, {5939, 894}, {2743, 415}, {4266, 664}, {2106, 334}, {826, 134}, {4006, 904}, {1321, 331}, {1948, 647}, {22824, 14732}, {793, 816}, {-91, 203}, {-997, 1014}, {-634, 638}, {-930, 902}, {-358, 312}, {-1224, 242}, {-790, 149}, {-2869, 513}, {-6412, 1076}, {-4189, 664}}); - TestOptimalLinearization("84648d7e00851fb02200018604a232010185649025020084139c5b0300863fc31200000384248d2d010003843d822e020002816f9c360400018432830704000009851fa258060000048045826d060001008618c665070000000881138c4305010008825497140305038263985006030002845e9d0404030000000c8140884a010402000986549e79030401000380198b7c03030001011382409164060300000011831598630701000000001181778c2b070200000000000f82118565040005098464b735040300000000007b8863010501001181229368020501000e82039006000300038014817f010001000000000003804e8d080100010000001b00"_hex_v_u8, {{4112, 1539}, {2265, 900}, {8705, 4603}, {2414, 2781}, {76, 1413}, {-1707, 2591}, {-854, 375}, {-4513, 1397}, {-3611, 740}}); - TestOptimalLinearization("6f856d0087059a220172853002813d9a2c038730867604803d820c05842e9b53068066806e07873bb577088146922009847891710a865ba91f0b8018825d0c807e8b550d803789560e810e9c370f8361a271108455c650118440c30b1282068341137f8939148010841515802d917b168736c03217871f801718847ac31819805a211a82569d310000000000000000000000000000000000000000000000000000001b803a916b01000000000000000000000000000000000000000000000000000019836d912a0200000000000000000000000000000000000000000000000000001980348345030000000000000000000000000000000000000000000000000000168124804004000000000000000000000000000000000000000000000000000016843eb63705000000000000000000000000000000000000000000000000000015856c932a0600000000000000000000000000000000000000000000000000001580068a6507000000000000000000000000000000000000000000000000000013801f844408000000000000000000000000000000000000000000000000000012824cb6070900000000000000000000000000000000000000000000000000000f802c8a430a00000000000000000000000000000000000000000000000000000f8477d0400b00000000000000000000000000000000000000000000000000000e8319bf140c00000000000000000000000000000000000000000000000000000d816e9a2c0d00000000000000000000000000000000000000000000000000000d835c886b0e00000000000000000000000000000000000000000000000000000d81709c680f00000000000000000000000000000000000000000000000000000d821f9f161000000000000000000000000000000000000000000000000000000c802582151100000000000000000000000000000000000000000000000000000b84488b0b1200000000000000000000000000000000000000000000000000000b81679e591300000000000000000000000000000000000000000000000000000a8741c4261400000000000000000000000000000000000000000000000000000a805c975b1500000000000000000000000000000000000000000000000000000a7b8946160000000000000000000000000000000000000000000000000000068255820717000000000000000000000000000000000000000000000000000006810b8178180000000000000000000000000000000000000000000000000000068656ac4419000000000000000000000000000000000000000000000000000005810180081a0000000000000000000000000000000000000000000000000000058447a3081b000000000000000000000000000000000000000000000000000004864e960b1c0000000000000000000000000000000000000000000000000000038273a1501d0000000000000000000000000000000000000000000000000000038304a6161e00000000000000000000000000000000000000000000000000000282189d3e1f0000000000000000000000000000000000000000000000000000018338b83820000000000000000000000000000000000000000000000000000000815f92662100000000000000000000000000000000000000000000000000000000"_hex_v_u8, {{4584, 725}, {4364, 762}, {1750, 317}, {4185, 1078}, {1232, 326}, {683, 183}, {408, 114}, {1745, 1029}, {198, 189}, {18555, 18373}, {188, 267}, {96, 292}, {68, 257}, {-196, 469}, {-630, 604}, {-774, 712}, {-203, 165}, {-1478, 974}, {-291, 180}, {-1945, 470}, {-738, 172}, {-3548, 702}, {-755, 134}, {-2029, 359}, {-1206, 186}, {-1582, 220}, {-3524, 460}}); - TestOptimalLinearization("832a8e4f008160850201854bbe4e0283429e1e0382558b2404872c937d05831593610672801d0780088b0c088708a5330982159d510a865db6010b83618d160c8526b8030d824f89520e813090590f80598d62108637b42a1181348e6d12863eb44a13863bc76d1483329779158543b65816813d9a141781198f4618810d934d00000000000000000000000000000000000000000000000000188319ad1601000000000000000000000000000000000000000000000000188634c8740200000000000000000000000000000000000000000000000017826087340300000000000000000000000000000000000000000000000011830d82050400000000000000000000000000000000000000000000000011860b8356050000000000000000000000000000000000000000000000000e807c9141060000000000000000000000000000000000000000000000000985349100070000000000000000000000000000000000000000000000000100"_hex_v_u8, {{774, 136}, {1738, 317}, {4071, 843}, {945, 217}, {3564, 835}, {1059, 281}, {3413, 951}, {3429, 958}, {1999, 578}, {786, 469}, {907, 609}, {681, 463}, {385, 352}, {-79, 114}, {-14191, 11733}, {-1185, 252}, {-1319, 269}}); - TestOptimalLinearization("806c883b00852cb52d0184028f590285248a01000584149e6d0203872de672040284648f2905028554b02800000b8637b471010006860ca51a0402028405a80706000009842ebb39020307845d814d03030006817da346040300058453a9760700010003835c8f680309804a8f0e070200108739ae4c070200010580588310090002000382738e6f090200000c8559c940040501000d87198e190005188417a5560202040e816e803203010600098112956402031d8450a5700a000000000100188117981f0b00000000010013820ba5100406021a8311b240080201000101188060933d0106011b846dc679050301030b840db86c000b0b83619c26080003000000000e842a93440c0000000000000000068675cf6a070005000000001d817b92730307000000178608ac780401001384158255070301000000128449b62709000000000100108124824f020800001e82059501000201000000002281398258020100000001000e00"_hex_v_u8, {{6043, 1305}, {2111, 1592}, {16829, 16660}, {2522, 3629}, {-232, 292}, {-1546, 885}, {-4578, 1405}, {-1409, 389}}); - TestOptimalLinearization("853d9a0300872ce27c01855dc769028042831b0380268234048670b972058159931a0109815b9c66040782548d5d000b8263ab21020a805f86510401088261ab3b06000204811e816802060a8070805704050a8701ad740501010c852fb83f09000001000880538b4c0305048510c24904000a85479a3b030302128413b0290207078409aa5d060500000480518a4103090a805f8413080500000009841ead02040f80058173001b842d802d0903000002098448a96004030617841aba6a09000012835c950c030b011783099f700211840eb8440502080d810e8f79040a010f81588229020704058040080500050302068619a95d0d0003000000068440a122060a010000068518a070030a04248177957b05090104855cca650802040420830c850508050401010d8348a8690206022e71871f000104020728870ec35d020001000000000200"_hex_v_u8, {{6398, 1068}, {3769, 1008}, {1511, 511}, {6, 7736}, {-2660, 6557}, {-1198, 1987}, {-717, 747}, {-2735, 921}, {-2555, 645}, {-2677, 584}, {-9778, 2011}}); - TestOptimalLinearization("80278170008458b93c01840e9c220284358d1b0377800c04871ca3470580338c00068219a40807861f9b4f088200977309810a847c0a82398b2e0b814e9b760c8177915c0d8657a5360e872ba73a0f81290810847db55111854cae4300000000000000000000000000000000000012852bbb420100000000000000000000000000000000001181168d270200000000000000000000000000000000001186049933030000000000000000000000000000000000118304a5550400000000000000000000000000000000000f8338926b0500000000000000000000000000000000000f853c830e0600000000000000000000000000000000000f8530ba630700000000000000000000000000000000000f853191580800000000000000000000000000000000000e870d85570900000000000000000000000000000000000b827e83180a00000000000000000000000000000000000b874abd420b000000000000000000000000000000000008803689030c000000000000000000000000000000000008826287720d000000000000000000000000000000000007836daf3b0e0000000000000000000000000000000000078678ba550f000000000000000000000000000000000006855e877610000000000000000000000000000000000006815385071100000000000000000000000000000000000681200d120000000000000000000000000000000000058350af75130000000000000000000000000000000000028713db5e140000000000000000000000000000000000008257813b1500000000000000000000000000000000000000"_hex_v_u8, {{2372, 409}, {1851, 334}, {3742, 728}, {832, 179}, {1198, 375}, {1873, 654}, {2459, 983}, {2589, 1067}, {791, 441}, {382, 266}, {184, 167}, {6046, 9350}, {268, 510}, {263, 828}, {-7, 288}, {-158, 471}, {-428, 1037}, {-388, 339}, {-1690, 900}, {-1270, 568}, {-916, 278}, {-642, 182}, {-3042, 844}, {-3819, 1016}, {-3826, 816}, {-2475, 516}, {-3102, 621}, {-3131, 592}}); - TestOptimalLinearization("825a8f49008163894a018617c37e028211980d0380649505048345b34905805f976006864f840e07856bde290885638c5c09866bee300a8171805e0b8735db090c8564c6010d8117947d0e841abf260f81209259108559917811814789531284109f4d138325b5191480528b3a158401bf7616864aae10178554db4318800d856719871cc20b00000000000000000000000000000000000000000000000000001a843a994e01000000000000000000000000000000000000000000000000001981339d580200000000000000000000000000000000000000000000000000198644d25103000000000000000000000000000000000000000000000000001980468724040000000000000000000000000000000000000000000000000019810a8d390500000000000000000000000000000000000000000000000000198446b2120600000000000000000000000000000000000000000000000000188575c56f070000000000000000000000000000000000000000000000000017813a880e080000000000000000000000000000000000000000000000000014811f832409000000000000000000000000000000000000000000000000001481289f620a0000000000000000000000000000000000000000000000000011836ab4600b000000000000000000000000000000000000000000000000001186119c020c00000000000000000000000000000000000000000000000000118673b5060d0000000000000000000000000000000000000000000000000010845c93070e000000000000000000000000000000000000000000000000000d804b856b0f000000000000000000000000000000000000000000000000000d857d835d10000000000000000000000000000000000000000000000000000c81469a5e11000000000000000000000000000000000000000000000000000981548a511200000000000000000000000000000000000000000000000000088661c1371300000000000000000000000000000000000000000000000000088119867b1400000000000000000000000000000000000000000000000000088467cb101500000000000000000000000000000000000000000000000000068526a4451600000000000000000000000000000000000000000000000000068278aa281700000000000000000000000000000000000000000000000000068329973818000000000000000000000000000000000000000000000000000582688425190000000000000000000000000000000000000000000000000005853988131a0000000000000000000000000000000000000000000000000005862098561b00000000000000000000000000000000000000000000000000038222a55c1c00000000000000000000000000000000000000000000000000038166a4101d00000000000000000000000000000000000000000000000000028730ef3b1e000000000000000000000000000000000000000000000000000183798e511f0000000000000000000000000000000000000000000000000001836d907620000000000000000000000000000000000000000000000000000000"_hex_v_u8, {{7128, 1003}, {1584, 223}, {4155, 641}, {4115, 666}, {4415, 919}, {797, 210}, {3016, 970}, {677, 355}, {1212, 857}, {878, 867}, {327, 975}, {111, 369}, {-1440, 17399}, {-303, 893}, {-339, 488}, {-586, 825}, {-1001, 633}, {-1284, 732}, {-510, 281}, {-438, 203}, {-745, 340}, {-2403, 806}, {-925, 266}, {-4294, 1052}, {-4252, 993}, {-4536, 885}, {-5353, 964}, {-7198, 1072}}); - TestOptimalLinearization("83158670008454b00201853eae2100038357ac07010384369d5c02028429822b0007801e887b010482216f050001800a877a0600008603a0410403800c873105000c8559ab0c040886199159070001038374b0290103108050807c0205010a830cb359040003010e8413926f04030107807c85220703000000058631af6009000001000a8637a46305050185609360070102000110846cc57b08020100000d6587160805000a8240a87007020201158551874806040101128177974c03080d84368c5f060400041a8559905a040204000c8422903002070513850ead0c09000401001d853dbd51070202020101018574d03d060009001c8104885e0c0200010103867b853c050007010b8158803c00090301118019847605060001000100038361ae5807020202000000058566ac5a0401040100010101835b854f07010000030001098237a37c0402010002001986608e5102040102001f855da12f0201000000010000"_hex_v_u8, {{3137, 724}, {1966, 694}, {2184, 1015}, {1077, 671}, {-56, 417}, {-4305, 19152}, {-424, 603}, {-2200, 861}, {-6216, 1876}}); - TestOptimalLinearization("8711d24400834a8e460180458b4302841fbf3200028025883800068672d2640104841fc210020104856fbd3001078039820e050000018175930b03038174915d070000008469864b011086248a4004098475a8040701000a844e925c080000000d8157a0540302108442c13504020f8162895105020685169902050401128559c2360101020b81568a5207000300028427c340060500001180118d520400000204137a835c0901010001118318ad6606010204000a847c8f39050805835da52600248455cb19050206048400b27b010c048604b97b0302080a842695560024835f96790002158530bc2f030703038365a02f012d807481580800040003001c801e851e01218631a40503050004218535c7030405000413800e82080202040602846ec55f09020002000000000017831fb37904020104000000001f85588150030005010101000885449c3d0600010400000f872e8f3f080101000100000e804a825106000100011e81619a5c03010200000c80118b1301010102002c00"_hex_v_u8, {{5346, 1041}, {12977, 2549}, {3992, 879}, {604, 165}, {9466, 2925}, {10459, 5394}, {1398, 1369}, {-5465, 2673}, {-3270, 1378}, {-25877, 8528}, {-4167, 688}}); - TestOptimalLinearization("845c9571008502c1220180458c6002822dae760381738272048546dc02058710ac1606826c9a240780108c6d088563b973098261b34a0a8625b4170b8532b2110c8376813d0d8424c34c0e8031911a0f81179d031081308c0911872abb6b128670a65813853ab85c148678f60a158672f17316843ba46617865d8214000000000000000000000000000000000000000000000000188537bd66010000000000000000000000000000000000000000000000188669c638020000000000000000000000000000000000000000000000188343b60c03000000000000000000000000000000000000000000000018835bb632040000000000000000000000000000000000000000000000188303b4090500000000000000000000000000000000000000000000001783039c2e060000000000000000000000000000000000000000000000178455c17207000000000000000000000000000000000000000000000016802f8b16080000000000000000000000000000000000000000000000158619a50309000000000000000000000000000000000000000000000014837db56e0a000000000000000000000000000000000000000000000014866897370b000000000000000000000000000000000000000000000014843f87570c0000000000000000000000000000000000000000000000148651ca440d000000000000000000000000000000000000000000000014863cde0f0e000000000000000000000000000000000000000000000014820990560f000000000000000000000000000000000000000000000014820a826710000000000000000000000000000000000000000000000013798c281100000000000000000000000000000000000000000000001182039f0212000000000000000000000000000000000000000000000010833dbc42130000000000000000000000000000000000000000000000108377a51b1400000000000000000000000000000000000000000000000e83649e3a1500000000000000000000000000000000000000000000000d870beb4f1600000000000000000000000000000000000000000000000b83008d401700000000000000000000000000000000000000000000000b842dc51c1800000000000000000000000000000000000000000000000b8359c5141900000000000000000000000000000000000000000000000b835bbe521a00000000000000000000000000000000000000000000000a8255876b1b000000000000000000000000000000000000000000000007824b97161c000000000000000000000000000000000000000000000007834ca4411d0000000000000000000000000000000000000000000000058673a6301e00000000000000000000000000000000000000000000000287218e731f000000000000000000000000000000000000000000000001835e8d622000000000000000000000000000000000000000000000000000"_hex_v_u8, {{7621, 1016}, {3067, 429}, {5953, 838}, {3365, 481}, {1165, 177}, {4390, 676}, {4241, 770}, {3694, 826}, {880, 197}, {1746, 492}, {2419, 699}, {2891, 1040}, {2540, 1008}, {32264, 19146}, {945, 606}, {202, 989}, {-244, 394}, {-556, 703}, {-1018, 1057}, {-566, 469}, {-1564, 1000}, {-2434, 921}, {-2446, 631}, {-2401, 588}, {-6088, 956}, {-3397, 515}, {-6952, 1035}}); - TestOptimalLinearization("805683130081759877018501ac560282608b1e038703b72f048554861d058445a50606856db672078359a70f08864abd4f097e86010a806d82030b82048b470000000000000000000000000c8712ce7e0100000000000000000000000c8470947b0200000000000000000000000c840e9d100300000000000000000000000b84539e0e0400000000000000000000000a8613b00b0500000000000000000000000a8346863906000000000000000000000009863ac27507000000000000000000000006870ebe7f08000000000000000000000005860d842109000000000000000000000005845589030a000000000000000000000002845588460b00000000000000000000000180198b490c000000000000000000000001812b972b0d0000000000000000000000008328a3770e000000000000000000000000872fa0700f00000000000000000000000000"_hex_v_u8, {{3577, 877}, {2923, 769}, {2435, 709}, {783, 480}, {-1399, 8615}, {-337, 909}, {-477, 582}, {-642, 725}, {-1406, 752}, {-804, 388}, {-3142, 915}, {-4096, 1038}, {-2364, 552}, {-4347, 954}, {-1558, 299}, {-805, 153}}); - TestOptimalLinearization("8327982d0080608f67000085299d2a0100847b8207020082769438030082479f0b0202822a996a01000887298a350100098432a61f010883029b5b04000006870ec96a03048172812b03010008824d916f010102000c833aa8040110801a847f0402000002832c862104000000000a873d9c060202010383208e7803010110815d1101041268870f050001851254010e8124804a020411822c9028060001000e866d8a77030105836ba27e001a8503890804030116857b8f620110850ba7510008188704b103010201001c857cc54f000001000000"_hex_v_u8, {{8000, 4089}, {-935, 11933}, {-3202, 1028}, {-2601, 779}, {-4520, 892}}); - TestOptimalLinearization("8678e51700857aca3901844ab2170282049f5f038003895f048638b6740405861f7e0208804491420206842e83130301078100901e02010b852bac6104030281759b31030301058533a67d02098275aa0108000000028178865107010001098336942a02050f841d99450305010e8501ba150304010a820b853205040a836eb53c060501057a83340904000004815e846b050416820d852b03090e845ebb310b020100000b8702835d0212815f9044000d09867ea171001e80359138020705178106880e09010000050f864fc97c040504011683109034030b010b824c8737080202000300000e847d8045090202000101000d835587720507030018862c9d00060500050b820587090608030000008461a5000103020003208601ab780106010102000183069130010305058734844f050200010100000004872fdb12050000000102000100078313ab200203020000248404a92503000101000100"_hex_v_u8, {{497, 327}, {-4592, 24583}, {-360, 1076}, {-2707, 644}}); - TestOptimalLinearization("87139152008053853701864db30c0280338815038544b2040486788f4f05841e841e06862ea22907823d8f150886706f09837b872e0a830e9f7f0b8465c07b0c831eab0b0d810d825d0e832b81100f8435a76a108602b63811810f897c000000000000000000000000000000000000118445b63d01000000000000000000000000000000000011847fc24c0200000000000000000000000000000000001080558c3f03000000000000000000000000000000000010861fbd0304000000000000000000000000000000000010871fde1805000000000000000000000000000000000010815c93240600000000000000000000000000000000000f8726b74c0700000000000000000000000000000000000e817c823b0800000000000000000000000000000000000e865e8c220900000000000000000000000000000000000c8309833a0a00000000000000000000000000000000000b8000854d0b00000000000000000000000000000000000b83049e620c00000000000000000000000000000000000a82619d510d00000000000000000000000000000000000a870899120e00000000000000000000000000000000000a7d670f00000000000000000000000000000000000a8354a83c1000000000000000000000000000000000000a8159941111000000000000000000000000000000000008821da75e12000000000000000000000000000000000007807c8f6013000000000000000000000000000000000007835d840f140000000000000000000000000000000000038212a00a1500000000000000000000000000000000000383039a0c160000000000000000000000000000000000018605c2501700000000000000000000000000000000000100"_hex_v_u8, {{3548, 898}, {3266, 836}, {2613, 693}, {3334, 973}, {21647, 16912}, {849, 990}, {285, 521}, {-52, 125}, {-328, 605}, {-222, 380}, {-423, 128}, {-1353, 345}, {-864, 213}, {-1961, 481}, {-3970, 927}, {-3551, 709}}); - TestOptimalLinearization("8225830d00801c874a01832393380281088e7c038600d033048639927a0581249631068324b3150782649f4c08816840098527b34b0a802c816c0b850a8f040c866cc57e0d811b90350e801a8d5e0f80308c2710810f917011800b835f00000000000000000000000000000000000012836ebc6d0100000000000000000000000000000000001281659b6c020000000000000000000000000000000000128375980a030000000000000000000000000000000000128746857a040000000000000000000000000000000000128170960d050000000000000000000000000000000000118025825f0600000000000000000000000000000000000d810098330700000000000000000000000000000000000c8572b06c0800000000000000000000000000000000000b852da800090000000000000000000000000000000000098427a87c0a000000000000000000000000000000000009806c83380b0000000000000000000000000000000000098470bd020c000000000000000000000000000000000008852b845c0d000000000000000000000000000000000008825f6d0e0000000000000000000000000000000000078151902b0f00000000000000000000000000000000000382369d1d10000000000000000000000000000000000003835f8a7e11000000000000000000000000000000000003855f864c120000000000000000000000000000000000038640bc4013000000000000000000000000000000000003861fa83e140000000000000000000000000000000000038447ba3e15000000000000000000000000000000000003802c8e54160000000000000000000000000000000000018653d11b170000000000000000000000000000000000018638cb2518000000000000000000000000000000000000866fbb471900000000000000000000000000000000000000"_hex_v_u8, {{943, 154}, {4543, 1004}, {1208, 271}, {2086, 484}, {1022, 264}, {549, 156}, {1308, 547}, {1277, 953}, {1026, 778}, {12943, 11680}, {486, 863}, {366, 811}, {445, 1094}, {-55, 479}, {-240, 165}, {-304, 139}, {-1110, 337}, {-3876, 1007}, {-1479, 368}, {-1935, 438}, {-4883, 952}, {-5262, 979}, {-1626, 256}, {-3959, 622}}); - TestOptimalLinearization("813c865a0080178a6f0183449e0202836ca622038446c40d0485028e6e0405816fa17203026c865604028419c03b000e82148c0f0500098351997a070103861b9f0405020a8542a07b07010002861383700111832e89530111860a830c000c8342b138020b810e97660704000006821ba6330803000008855fc612050401000d8028915e03040308832cb03c0a020000000000048509c97d0605000100118167820f07040200086586710703010000000b85762804080104851dcd4105050217854acb3a0a0301000000000f8514976b04080c83449a100808000009874485630b000102010c85799c750d00020001001b80368d0f07030005098259a0700c00000002010a8056876b050b0000001581328a660e0000000100001b807f800405060600098569850a0307050012860a933506040003000200058463b22f09020004000000000021805188430401020602188052853305010203020204824b9e150c0001000101000000248114842c0501030101030a851d944c0503010300238449a2560a0201000000000000000023844ea548070700000000000f8277ae15020700011981479a7e070500000000000000000d81339c5a070003020000000000000016867395490702000200000100001080278938030302000100007a81150400020001318457b11200010201000002827fb116010000010000002300"_hex_v_u8, {{4709, 1055}, {2513, 620}, {2218, 909}, {6605, 3186}, {6218, 3702}, {703, 1507}, {20, 886}, {-2372, 6067}, {-10262, 12450}}); - TestOptimalLinearization("803a8f330086548209018265ac21028521bf2e0104800b844d02018321a05d0006835e933e040003835792230400048047865703068201a07d04068662a16d0308865ad476000e8431bb620200020b8264841503010c8625ba5704000209837d9d52021686378e68020e837b8174020e840e80590301060383329a4007020100118262885c0305010a834d8d2a02128133964d0600040d8437ac2a0503040005816b810705020419840cb2440d00000100000b865ad07005030003118419ae21060201030586748076060005000c80068a0e050103030006870dc31208020000020010863bc91f060100020301000a80218b4f0400020d817c8e6f080100020201000880108c4f010d1b834db0320607000017841ca15c0500040000020478853200020100000000001300"_hex_v_u8, {{3922, 1781}, {3529, 2772}, {16566, 14073}, {579, 1338}, {-1016, 380}, {-7368, 1740}, {-808, 161}, {-872, 144}}); - TestOptimalLinearization("83049f4a0083539553018011896b02843fae55000583309e310201841ba76701028628b504010204850ea4570009820c846d030000078451a60303010006802c8877030203857a9e280304805e857005010c83798c7001050c8441811d0403018550bd5f0305008636c9210701000e846d9e1d010311821d933c06020006847e961a0503000a7a8945060200148610bf4d0115842fa97b0402040476841c010716872d28040201058631a10a0104001a81579d3a060001000100001681078c43020401011b8438844406000001000000000f83678264070000000000000c820c8800040101010017814c9103030300000011840c912200000000001200"_hex_v_u8, {{2085, 516}, {-1, 2091}, {-214, 2450}, {-2803, 3167}, {-16800, 11295}}); - TestOptimalLinearization("8600ce6f00678071018613875102865ed14301000384579a0c010103854cbe730201028376900f03010278810703068355833202058354ab7e03000b844b9a370402098269a4780303068300a66e020001010c8519a4670300020a84319c090600000007698027030204872ac12f05010100000782369e5106010000000f82549d5006000100000f845b9a7b0601010c8536a42e0601000b8325b33a0503010006826498040400050d80488e5702158206906e0702020b6b86170b000100088745ad1703108406aa3b03090e823b9117010b01821394500107148626c44e0b00000001000f82019f2a0103030001128153900a040401000000000d866bde1c03060000000d80548e180503020001068455a7100604010000001e867fd30e0a00020000000000058505891f060101000000000004840b9d3a0303010000000000268631bc12050100020000000500"_hex_v_u8, {{9901, 20654}, {1369, 3124}, {-656, 773}}); - TestOptimalLinearization("851a8e58008454b44d01841a8c2902856eb42e0380314404841bbf4b0582368b3a068067897407823ca94d088420823a098555be160a823a87700b835086700c8350845e0d8747984d0e8137870c0f810f8006108417ab0911842fae6c1280358071138571c674148734d83f158327aa76168228892a178706d45018821e97001983479b591a826ca46b1b856daf59000000000000000000000000000000000000000000000000000000001b8428b309010000000000000000000000000000000000000000000000000000001a826f9021020000000000000000000000000000000000000000000000000000001a86729e61030000000000000000000000000000000000000000000000000000001a8643880604000000000000000000000000000000000000000000000000000000158646cc0e0500000000000000000000000000000000000000000000000000000012846e935e06000000000000000000000000000000000000000000000000000000128551884f0700000000000000000000000000000000000000000000000000000012811e9836080000000000000000000000000000000000000000000000000000000f82308c66090000000000000000000000000000000000000000000000000000000d865ea4640a0000000000000000000000000000000000000000000000000000000884269c770b00000000000000000000000000000000000000000000000000000008831d80570c000000000000000000000000000000000000000000000000000000068531b4620d00000000000000000000000000000000000000000000000000000005865e92390e00000000000000000000000000000000000000000000000000000004855f892d0f00000000000000000000000000000000000000000000000000000003863c8b0110000000000000000000000000000000000000000000000000000000038374aa22110000000000000000000000000000000000000000000000000000000381078e2712000000000000000000000000000000000000000000000000000000038153932c13000000000000000000000000000000000000000000000000000000018321ad5814000000000000000000000000000000000000000000000000000000018318ba1b15000000000000000000000000000000000000000000000000000000018469a57516000000000000000000000000000000000000000000000000000000018310854e17000000000000000000000000000000000000000000000000000000018543a57e180000000000000000000000000000000000000000000000000000000000"_hex_v_u8, {{5480, 1030}, {4602, 881}, {2811, 551}, {4043, 853}, {3062, 687}, {3415, 878}, {1536, 414}, {698, 231}, {797, 438}, {518, 311}, {661, 424}, {568, 442}, {1004, 794}, {504, 592}, {367, 592}, {221, 672}, {67, 271}, {34, 177}, {-526, 14670}, {-108, 541}, {-616, 849}, {-663, 863}, {-769, 956}, {-1245, 990}, {-2033, 1010}, {-1105, 495}, {-1916, 678}, {-2491, 745}, {-3117, 877}, {-980, 263}, {-3333, 680}, {-3790, 536}}); - TestOptimalLinearization("82549265008464d27c01866ab47902837da12a0380368f74048738dc4d05842e8b3b06853dc84a078661ab22088454a16b09865f957f0a8279ab2b0b837b84050c837dc31a0d837db5180e7b816f0f8346ac4310800b883d1180148709128349a63c1380629800148638ae3f15802c8b59168223ae4117801d8e1718812f893319853bdc3b1a841caa5b1b8354aa55000000000000000000000000000000000000000000000000000000001c870abd4d010000000000000000000000000000000000000000000000000000001b85768103020000000000000000000000000000000000000000000000000000001a801c8861030000000000000000000000000000000000000000000000000000001980658e150400000000000000000000000000000000000000000000000000000019826da47005000000000000000000000000000000000000000000000000000000198100884506000000000000000000000000000000000000000000000000000000188528d056070000000000000000000000000000000000000000000000000000001880718a5d08000000000000000000000000000000000000000000000000000000178677ba060900000000000000000000000000000000000000000000000000000017815889110a00000000000000000000000000000000000000000000000000000016813187200b00000000000000000000000000000000000000000000000000000015804a800a0c00000000000000000000000000000000000000000000000000000015847a81550d0000000000000000000000000000000000000000000000000000001486799e420e00000000000000000000000000000000000000000000000000000013835cb8120f00000000000000000000000000000000000000000000000000000012865ff84910000000000000000000000000000000000000000000000000000000118403ac6111000000000000000000000000000000000000000000000000000000108656db361200000000000000000000000000000000000000000000000000000010815da06013000000000000000000000000000000000000000000000000000000108740f30c1400000000000000000000000000000000000000000000000000000010843ad1361500000000000000000000000000000000000000000000000000000010806a92421600000000000000000000000000000000000000000000000000000010874acc3017000000000000000000000000000000000000000000000000000000108001897218000000000000000000000000000000000000000000000000000000108213a100190000000000000000000000000000000000000000000000000000001085159f141a0000000000000000000000000000000000000000000000000000000e806288681b0000000000000000000000000000000000000000000000000000000c842d86401c0000000000000000000000000000000000000000000000000000000b860bb3081d00000000000000000000000000000000000000000000000000000008814ca17f1e0000000000000000000000000000000000000000000000000000000680418c4e1f00000000000000000000000000000000000000000000000000000006820e98212000000000000000000000000000000000000000000000000000000006856db851210000000000000000000000000000000000000000000000000000000300"_hex_v_u8, {{5374, 740}, {1600, 226}, {4365, 637}, {1082, 182}, {4709, 829}, {3468, 637}, {2526, 585}, {2197, 637}, {2833, 993}, {14949, 22604}, {69, 202}, {-130, 886}, {-171, 762}, {-649, 344}, {-611, 256}, {-751, 241}, {-4007, 1034}, {-625, 156}, {-1617, 398}, {-3689, 877}, {-971, 229}, {-2929, 643}, {-2795, 596}, {-2240, 332}, {-7781, 991}}); - TestOptimalLinearization("863e9b20008701a22e0182579614010281579c03010381008737030180078e2603028345911504028417a101030981318d650508867b9a11070006823c924f0105058647a60b050101058579a75b07010001861bdf4c060001010c834e841d0700010106855dca03070102008633dc7f03060d8654bf39090000020c854bc4370802000103846aac180c000100018058811e03138727b30b0a0200010a845a902206050104804191120703010108844cc60f030b00188530b810090000030d8434be3403070d833fad1b00298038953206051d801a520606000f8216a05a030b218007891e020911815b9716030b0b867ab553050709802391740f030000010007817896370d010003000200168041880803080518816ea42a050902040e872d8a09080200050302000e8576960e050b010400098330bb6e0c06020200098418ad6a1002000300000000148704c07008020405030011851f8657060d040e8619be7016000101000000088559d32c0213078307891a08040a00011e8313b627010c0104001e853ad64004070300051b815d834205030c038423aa3904040701030001128155a3390f000000000500308262a43b0a000107010b8136861d0505000701010f82359b1307010005000401001e8028841605000603010200002981679d16030705000300298710cd6c080601010000000101308055803e0802040100010002001681758e2a090400010100000100258741ac0d0a00030001030000000680738e2c06020500000001001783629a68020703000001098707dd08000001030000001000"_hex_v_u8, {{3242, 1160}, {9343, 4022}, {7247, 25626}, {-574, 1753}, {-2604, 5019}, {-2887, 1089}}); - TestOptimalLinearization("83638b0300845bac6801871ac51d028278937a036a5004855494040405814883580405872dd30f030203816f9009030301856bb80f0501000684008658030406805380100400068632a8520500010b80658e2f0403010580068a340702000002845cae500802000000806b8c350400040584319f5a0900000000086f827c09000100000184627b06000004038341844d0603000000001181208d070502000102048043760600000200000010862fad260603000000000a817786690402000003000e84059e410305020004861eb63a0401020001138016862600080486419756020500010008833ca46f04040000001182019658020000000200000800"_hex_v_u8, {{2932, 731}, {1341, 504}, {3541, 2737}, {492, 640}, {40, 106}, {72, 211}, {-779, 2654}, {-2914, 8443}, {-359, 577}, {-2424, 572}}); - TestOptimalLinearization("8015812700866ade5401811c8f7b028442ac3003866fc73d00058220984901048676c4440204813194740500057b8b1b060005845fa71e050106837bb34d060003853abd55070001008519ab1102030e824f94580602000a8405b15c0403020b806a8b78040303088724be690603020380708230080003000d851f9b5d05050000008674dc540401050011864f9652060200020110841c8a61090001000101832c8819060303000005814b9c160601010400068109885a06050002018304b203050001061686419e69020b00128638c97d0a010100000000000018856dc2060302080000028419b54c0307030781568573090300000000000000028428a7150702000100001d864db25f020207000a85409403000700000018822f920c0300010201001483409a1a0501000100000013856ac8200400010000010011803e8f620500000000000019836692540302000000208548895a00000000000c867ecc2801000000000a00"_hex_v_u8, {{6122, 1002}, {7354, 1720}, {2575, 735}, {1254, 454}, {1609, 1061}, {302, 747}, {-6224, 20869}}); - TestOptimalLinearization("8677a44400823d9b1101847c893e0102831ea2130201865b944502028560ac640301856cc01101088644cc2c0302867ea77d0008843d8949040202843a9d0307000081528f5707000005804e8c5b0403000585169c7e06000201834e8e0d0503000d835e96250500000f8628a9550104078018847d0302000201821f90780301000002000681648442030103028433976b070000000000000e844a9116040202000d82349016000880158b240600010100108006831101060001850bb04e0101010100088723835a010002010c830593360203000003811a8e150400000000001c7f8168010000001300"_hex_v_u8, {{2402, 1015}, {2700, 1506}, {671, 764}, {1129, 1309}, {-7302, 12461}, {-1410, 818}, {-971, 282}}); - TestOptimalLinearization("8744ad0c008552be55018377a07f02844ec32802038655a103020482109b72020006867ee92c030006847fb879040003867cc5770301098620c77d06000001834e9c6b050102831ea745070000048736e7040309854bb64e04000a82129d600303068327847c03060c81749e6a0604000c8616af13070400008062915d08010200078007880206030301823e815106000609862ab9220502178451b018080000010c82469e2a0803000001058579c33c090000020116852f8b210704000001068168a05d04070001148616c21d0801020001000e8327991f05000f8025860a0b000002010003862f8a250c00010100000b8002480a00010002000b801f877005000600011e8539be10010b011c8341b558060302000001001a83758b0c09030000000000038738d71b070500000000010000088527c943070005000001001d81789e5204060300001c850eb12a0b03000100000000058676d84b0602010103000b834aaa310202020001000100001c8425af0c0302020001000100000d8107942e02010201000200001c830f9f330000000002000012830ea4700200000000000000000d00"_hex_v_u8, {{7322, 1810}, {2404, 2903}, {8842, 11211}, {4511, 6807}, {764, 2139}, {-1680, 551}, {-4367, 1277}, {-10769, 2999}, {-2074, 527}}); - TestOptimalLinearization("82159935008379b66e01830bae7202803d87690203826ea53b0302821a993303038408b52a0502864de64005028326bc7b050106827a9b050508842ace1c010f836f966204020865810a080106816ba5640703018270844306010301851f8e69050201000d8500866c0505000b8357ac7d040500098542881e040109822f8451050303048257985708010400028555bd29020e8116875e0603010211865c9f0906010408846db41b0206050786259654050503000011855ac662080300010100068655c91b020910830bb7540d0000020000000d8563da4d0e0000010000001481148d1f0e010000010012831193360a000004010a860ece440807000100068402b614060404020e8712da6e06080001028377997c070401040000018224a23c040800041e805f976e0c0201000200018655e22305060501088656a83c0801000401011e8248a140010a02002385633903010703011c80528207080302000200002780038e130c01000300000000268421330701020103010b800682590a0102020000001f863ca66005050202012b831fb146070300000202000024834c9f5d060003000100010d840dc01a040201010319857a8a2606010101000001000009824f814701040301136e876d05000202010000000c871cad4d0107002c803d884203000402008446cd4e0000010000000d00"_hex_v_u8, {{10199, 1606}, {3065, 523}, {1786, 1053}, {1089, 913}, {792, 773}, {1104, 1232}, {13868, 19409}, {-4512, 8170}, {-567, 110}}); - TestOptimalLinearization("8673c728008004810c01805e967802866fb254038536a93f048712a43d0584498d14068610c30a07822dac46088401a72f09860082450a8279a0490b6a853e0c817c991e0d815795060e8349c2490f7e8972108438b610118616b67f12807485361382058940148739c34615847ea91016805f8421178662d04718805b835019852b97491a857aaf401b832090231c810991491d802184130000000000000000000000000000000000000000000000000000000000001e855fb371010000000000000000000000000000000000000000000000000000000000198563b31d0200000000000000000000000000000000000000000000000000000000001980178c10030000000000000000000000000000000000000000000000000000000000198201867404000000000000000000000000000000000000000000000000000000000018873b86670500000000000000000000000000000000000000000000000000000000001382279e3e060000000000000000000000000000000000000000000000000000000000118442ae4d070000000000000000000000000000000000000000000000000000000000118707c3000800000000000000000000000000000000000000000000000000000000000f8533b9360900000000000000000000000000000000000000000000000000000000000e833d94160a00000000000000000000000000000000000000000000000000000000000e843381770b00000000000000000000000000000000000000000000000000000000000e811590520c00000000000000000000000000000000000000000000000000000000000d8729993f0d00000000000000000000000000000000000000000000000000000000000c82149f050e00000000000000000000000000000000000000000000000000000000000c8648c6740f00000000000000000000000000000000000000000000000000000000000c832fa20e1000000000000000000000000000000000000000000000000000000000000b860e862711000000000000000000000000000000000000000000000000000000000009842f923212000000000000000000000000000000000000000000000000000000000009815c967613000000000000000000000000000000000000000000000000000000000008824aad4714000000000000000000000000000000000000000000000000000000000008854c844715000000000000000000000000000000000000000000000000000000000008851da76b1600000000000000000000000000000000000000000000000000000000000781449e7517000000000000000000000000000000000000000000000000000000000002832e8d051800000000000000000000000000000000000000000000000000000000000000"_hex_v_u8, {{1532, 222}, {2915, 429}, {697, 126}, {3528, 696}, {4357, 912}, {4628, 1011}, {1679, 380}, {1411, 343}, {4387, 1081}, {415, 106}, {2696, 766}, {3104, 890}, {3306, 1007}, {672, 389}, {411, 244}, {296, 219}, {906, 713}, {134, 132}, {-227, 896}, {-3629, 13571}, {-188, 691}, {-356, 844}, {-500, 1083}, {-468, 910}, {-1696, 1065}, {-899, 558}, {-330, 161}, {-2614, 797}, {-3343, 867}, {-3385, 863}, {-3047, 706}, {-2051, 404}, {-2043, 324}, {-2980, 458}}); - TestOptimalLinearization("8063850a0084718e1f018627d96c028369c06503842ec7070480158a0505853fbf200683719c3e07806f906a088611df4e09816fa0570a863e94760b800485030c8307b4590d8642e7400e8459bf1d0f803461108259aa03118671ad171280708651138257907e14821986091582203b168527c013178315aa081880558e67198664c5511a872afc330000000000000000000000000000000000000000000000000000001b863b8d480100000000000000000000000000000000000000000000000000001b847f81610200000000000000000000000000000000000000000000000000001b8526852d03000000000000000000000000000000000000000000000000000018857d901b0400000000000000000000000000000000000000000000000000001884238e240500000000000000000000000000000000000000000000000000001885049c610600000000000000000000000000000000000000000000000000001880401a070000000000000000000000000000000000000000000000000000168349a2100800000000000000000000000000000000000000000000000000001581539c5f09000000000000000000000000000000000000000000000000000015810f96030a0000000000000000000000000000000000000000000000000000148406b8190b0000000000000000000000000000000000000000000000000000138005801a0c000000000000000000000000000000000000000000000000000013863c99570d000000000000000000000000000000000000000000000000000013842ea1130e000000000000000000000000000000000000000000000000000012810b8a5e0f000000000000000000000000000000000000000000000000000011861c8474100000000000000000000000000000000000000000000000000000118117903911000000000000000000000000000000000000000000000000000010850b981d12000000000000000000000000000000000000000000000000000010822d9d73130000000000000000000000000000000000000000000000000000108655c73614000000000000000000000000000000000000000000000000000010862baf0c15000000000000000000000000000000000000000000000000000010758c001600000000000000000000000000000000000000000000000000000f80739a7f1700000000000000000000000000000000000000000000000000000f8070856b1800000000000000000000000000000000000000000000000000000f837c8d4e1900000000000000000000000000000000000000000000000000000e806888691a00000000000000000000000000000000000000000000000000000b8570de661b0000000000000000000000000000000000000000000000000000098332bb0b1c0000000000000000000000000000000000000000000000000000098240ae6b1d000000000000000000000000000000000000000000000000000008861599711e000000000000000000000000000000000000000000000000000006821da71e1f0000000000000000000000000000000000000000000000000000038334af692000000000000000000000000000000000000000000000000000000200"_hex_v_u8, {{6688, 962}, {6183, 913}, {5814, 935}, {2756, 533}, {4112, 831}, {1141, 239}, {1887, 625}, {1151, 471}, {389, 227}, {1403, 958}, {-30, 416}, {-49, 180}, {-13972, 17369}, {-1102, 893}, {-1708, 956}, {-438, 240}, {-1721, 917}, {-1615, 779}, {-1905, 772}, {-629, 232}, {-2186, 686}, {-1117, 279}, {-1978, 429}, {-1474, 271}, {-3125, 564}, {-1904, 339}, {-3661, 646}, {-3062, 448}, {-3846, 562}, {-1792, 243}, {-8026, 1066}}); - TestOptimalLinearization("822f8a1500813c8e2c01812b92570280708513038608a92804835ca704058668d931068417a738078402a65b08853f9749098176994f0a81438c730b8261827e0c816c816f0d831d8a450e825a901f0f8105852600000000000000000000000000000000108338ab330100000000000000000000000000000010852dbe30020000000000000000000000000000000e82419630030000000000000000000000000000000d813c867c040000000000000000000000000000000b831b9d1a050000000000000000000000000000000b84069108060000000000000000000000000000000b854b967b070000000000000000000000000000000b8031820b080000000000000000000000000000000b81518a2e090000000000000000000000000000000b83208e010a0000000000000000000000000000000a8670d4660b0000000000000000000000000000000a860dce2a0c0000000000000000000000000000000a8451c1270d000000000000000000000000000000098543b1490e0000000000000000000000000000000883609b660f00000000000000000000000000000006843da97210000000000000000000000000000000068028897f1100000000000000000000000000000000842ab52d120000000000000000000000000000000000"_hex_v_u8, {{2562, 604}, {2588, 663}, {982, 316}, {2708, 904}, {8802, 12587}, {-198, 177}, {-961, 544}, {-1534, 843}, {-3237, 835}, {-704, 168}, {-2842, 568}, {-3479, 682}, {-4244, 721}}); - TestOptimalLinearization("8333b0280080278a4701831688680002870ecd590102866f74010581298e1203000280238a42030006648603040006850aac5b05000680048845020c8314866b000f8355b84a06000005856d814a070000058172823103020f8409b86904020c8664e05502050b824eab0501030681708f410014847dc92c090000000000018511993e0302010681548c17001a8276a87b050201000012816b933e0401030d853fa06b020604857ec0300901000000000b872dde14020700000f8252851c04000313813a8d0305000500088051816a04070000018228913a02081b8323854d002183458170050501000b8517ca10050201020015802f89210204178509c61503041682529401050102010686269150010003031a806e821c000002010204856798430100000101020e845498700104002000"_hex_v_u8, {{3156, 563}, {1594, 1161}, {3115, 10582}, {-3684, 5344}, {-423, 547}, {-4401, 3628}, {-1634, 871}}); - TestOptimalLinearization("810c8e3d008316881a01863fa11b02831dad01038049881804873d9a410203822e9f420302822299290204842d32040208874a8734020b80278a6b020b6884100408803b812505000e857ba64a0801000a874bc7760604088600aa69060980618e7a05060a8472a23a010b0b873bcf000604000e816d97620a01020f86409a730215872c8e22010c04801b8963010a18855c8b3f0a00010200000015864c98150701000401000a81428f60080005098458c254040601020d837cae5c04010a0c8273a56209050101000000058507b07b080200061080519068090003010100118310a0050503020000010000148727d92f0502020200001785599e740207000201000b8421905004010102010124854d8b0f00050003002200"_hex_v_u8, {{588, 201}, {3571, 2051}, {6111, 4552}, {5853, 5439}, {4559, 5181}, {-800, 860}, {-4457, 3265}, {-2115, 528}, {-5784, 1063}}); - TestOptimalLinearization("850c8f35008651ce2f0165807a028725d844038227a4150481378e1c058729b702068279a853076f8878088239a3380981228d300a805c85710b86559b420c8653a67a0d860eac270e823d8c0a0f82539142000000000000000000000000000000000f80068543010000000000000000000000000000000f825f8156020000000000000000000000000000000d83459166030000000000000000000000000000000b84209c0a040000000000000000000000000000000b807e9509050000000000000000000000000000000a80709452060000000000000000000000000000000a70823d070000000000000000000000000000000a8301a000080000000000000000000000000000000a8168806c090000000000000000000000000000000a8120865e0a00000000000000000000000000000009801583190b00000000000000000000000000000009857ed1480c00000000000000000000000000000006806082300d00000000000000000000000000000004801f89590e000000000000000000000000000000038103965a0f00000000000000000000000000000003801d822d10000000000000000000000000000000038459a3031100000000000000000000000000000002872eaf7f1200000000000000000000000000000002854b9658130000000000000000000000000000000100"_hex_v_u8, {{636, 111}, {5730, 1061}, {2332, 441}, {3585, 1065}, {920, 290}, {974, 311}, {2557, 979}, {837, 445}, {1825, 981}, {125, 101}, {2546, 9635}, {-215, 157}, {-269, 149}, {-223, 112}, {-3136, 1070}, {-418, 134}, {-2306, 729}, {-685, 159}, {-1413, 254}}); - TestOptimalLinearization("844f8835008631d1440183318e0a02801b896803863dc83402048525bb440304811a937e04000581669911040006872aaa100600058452b04607000480208c7005020681319777060200852dcc3c0701000b821ea3640801000481168f0808000201860c843204088715df6f0c00000000870ebd7b07030013816f9831021a82778d4200188018854a0c01000103825093730601011684298a2b0402070011832dad31030603098571cc760c00000001000000058704dd7b0b0000000000000000000b8257845005050000000000000000178630c00e04060000000001108435c159090101000000000100078474ba01050004068447ba4506030102000200028408490901030000000111850db1610a00020100000000001a8557c6570307000000011d8275ab4706000000010217648325010303188419801d04000600010012837ebd2202091785548e2f050000000103108028852702030001030383689059040300020102862aa26c010003000000002086199a08020003000000001300"_hex_v_u8, {{5282, 945}, {4698, 957}, {3874, 805}, {692, 155}, {14104, 3949}, {6151, 2252}, {345, 908}, {-589, 2663}, {-696, 870}, {-892, 981}, {-1375, 1112}, {-32657, 11825}}); - TestOptimalLinearization("824b8e1200805c8610018129801f028373a87d0380767f0486319546058649b858068623a50f07871ca14908805c9121098637af790a8668d1220b6480290c801e827d0d845eb6420e857ec3680f8600c332108517857f118126880100000000000000000000000000000000000012806b917101000000000000000000000000000000000011815e8069020000000000000000000000000000000000118468a40e0300000000000000000000000000000000000d8355ae150400000000000000000000000000000000000b832c99610500000000000000000000000000000000000a8720cb11060000000000000000000000000000000000098623b37c0700000000000000000000000000000000000880668f1b08000000000000000000000000000000000008835b9813090000000000000000000000000000000000088279892f0a000000000000000000000000000000000006802488110b0000000000000000000000000000000000038337a31a0c0000000000000000000000000000000000038574aa730d00000000000000000000000000000000000100"_hex_v_u8, {{5265, 1000}, {4404, 894}, {4377, 896}, {3553, 734}, {3692, 969}, {969, 459}, {456, 220}, {1443, 945}, {-64, 246}, {-80, 297}, {-448, 791}, {-4017, 6631}, {-664, 505}, {-577, 294}, {-1610, 603}, {-1713, 556}, {-2810, 884}, {-585, 164}, {-1038, 230}, {-4873, 1056}, {-3019, 597}, {-1209, 235}}); - TestOptimalLinearization("866db148008305944a018340810400038721c963010282528f4802028532a1260301852e954c030685778653050002668530010c806a4a020c8451aa0f030102866c8e250202000b812e9071060000000009852f875105010000000d834e98750400020003814b8b63040000020007840fa646050000020001812c891d0203021082428c7606000001000d822e875d01118502bf170701000006840a8e6c050002010a820c9b1c0204107c871f030100031682259a480401000300188676815a0107128034845b03030002138458a24205000000000013861ca528050000000001048560b41e0200000101000e80618757020200001300"_hex_v_u8, {{3236, 1005}, {3576, 1335}, {1060, 466}, {1984, 1492}, {37, 234}, {-3095, 13613}, {-556, 225}}); - TestOptimalLinearization("8260991f008662892d0001837fa91b01008401a85d0001870cad1f0101810c8658010681356a0206846b824c0400058661c47805000183058c7104028609914d06000a864fc143070004852fb7020601078132943c03040008845eb202040201048626a67f02000682358c18040004000384249049050000030781428c4c02020c8361962f030204028078873307000001010008821b986c0205010005853b8a0e070001000000000c8260956c0301040c862ca078030000010200186b825d010401000c807d930100040101821196590500000000000000088235880e020000001300"_hex_v_u8, {{1910, 8479}, {-3111, 8308}, {-1517, 401}, {-1281, 253}}); - TestOptimalLinearization("842ba05d0083138d6d018720e40a0268816b038548bc49000684269a620105840dab78030007850cc00c010009835486260200088667873a0300078065811006000103865b943f050303836db67905078749c8200700010b8742c257080001000d8351a3460500098604a67e060000108355896d0407000c8712b40005050004832e854607000400128421a30704060f8416944b020a01804e8d5207020100001081598f290209088422862b0700030306867cb04a06030100128733c8370005050e840a884d020105031b8477ba4404050100020886669d270203051886378d2e04030100020000000d8745db65020700000000198465845e0205001382059f3a07020001000000001c843ca06304060100001c854d8f670208000b81519352000004000f84598017000001000200"_hex_v_u8, {{6469, 1056}, {1595, 782}, {12744, 6989}, {-189, 1663}, {-1826, 9149}, {-470, 674}, {-615, 650}, {-8266, 5425}, {-5939, 1093}}); - TestOptimalLinearization("810e982400840a9a7e018619dc02028157a542038640a10b04844ec93a058055805f06872eb8660783718a1f08874bcc070980477a0a820194780b8345a66d0c8310a0420d8437b4660e8672af300f8225957310801a826f11807b877e128558d32c136e87581483299c7a00000000000000000000000000000000000000000015805f904d01000000000000000000000000000000000000000015831f922a020000000000000000000000000000000000000000158570be5d03000000000000000000000000000000000000000015863c88160400000000000000000000000000000000000000001480178919050000000000000000000000000000000000000000128563816406000000000000000000000000000000000000000012864bc86307000000000000000000000000000000000000000012841c9a7b0800000000000000000000000000000000000000001182029c6e0900000000000000000000000000000000000000000f8234922d0a00000000000000000000000000000000000000000d800582520b00000000000000000000000000000000000000000d8570cb7d0c00000000000000000000000000000000000000000c8471c94d0d00000000000000000000000000000000000000000c8013865b0e00000000000000000000000000000000000000000c83348a680f00000000000000000000000000000000000000000b811496721000000000000000000000000000000000000000000b850cd3641100000000000000000000000000000000000000000b8738905f1200000000000000000000000000000000000000000b6d812e1300000000000000000000000000000000000000000a7a81501400000000000000000000000000000000000000000a836ba6171500000000000000000000000000000000000000000a8736e1381600000000000000000000000000000000000000000a834a833c170000000000000000000000000000000000000000078340af00180000000000000000000000000000000000000000068460cd141900000000000000000000000000000000000000000686429d651a00000000000000000000000000000000000000000382179f3d1b0000000000000000000000000000000000000000038651b36c1c0000000000000000000000000000000000000000038405c04b1d000000000000000000000000000000000000000002874182401e0000000000000000000000000000000000000000028127827d1f00000000000000000000000000000000000000000100"_hex_v_u8, {{2465, 343}, {4765, 718}, {5953, 921}, {5398, 856}, {1618, 270}, {556, 110}, {3443, 695}, {2145, 528}, {1404, 385}, {3699, 1070}, {3096, 1010}, {1791, 650}, {575, 251}, {17859, 10290}, {151, 109}, {168, 122}, {756, 564}, {587, 956}, {286, 586}, {224, 1089}, {178, 867}, {-255, 295}, {-1136, 1080}, {-1971, 962}, {-1790, 668}, {-1239, 436}, {-494, 147}, {-2508, 619}, {-653, 151}, {-4079, 880}, {-4722, 971}, {-1127, 223}, {-2079, 407}, {-4927, 880}, {-4775, 753}, {-4198, 645}}); - TestOptimalLinearization("852dbb7700865eeb7601817ca676028220a65e000580368e660204850932030281369816030106872caf420208861bdc08020209861eba7403020880378d6703020b8253965b040209823f95360013826ab4040402048713bd3606010101817f88540009837cb26c060003000d81628e4e07000300058009811605000511817a9c10090002000005821e9379040700048656d7620500060b850e8d6803080008841a9f44040700138239a535060005010f842e81630605000114822a8f73040800000a8539b3580b010000028407c670020a0e811f0b050702058616cb1303081c8315ae6406040301001c806f9921020c16860fe23e040c038563cf050a0001040f8023842d020e16803f885c050700040182109c010206080d8242ae6702042c813ca3320209041f843ec61401030a1082659641080201020223864cbc42010e1e8442a279012980608866010b0010836c991e0106010f8637903f09010002001e820998050a0500000000108328b41c0200050a825a8d63000b0f827bb9030009108152923704020300020080298155060201020000048023802102093283758a2c000600010035805a8403030203218516c7410300010000000200"_hex_v_u8, {{6971, 990}, {2555, 380}, {2543, 416}, {1011, 182}, {9375, 2190}, {3834, 926}, {7100, 2111}, {24543, 8471}, {999, 354}, {948, 782}, {3401, 2813}, {599, 974}, {-2440, 4852}, {-946, 474}, {-9312, 3117}, {-3594, 1125}, {-1603, 393}, {-4641, 790}}); - TestOptimalLinearization("803894000087239a23018325873d02812fa0580100028315a2570200027c8a3f0300028608b21b030102870aeb0c05000283728121060000853fcb4d070000856ddb50020b802c927803030b8361c41105030a874af55b050209814d825101168319b7420600040e752f0601030e8054947c0700000d841ca56f0409817a26080501827cb2340108020c83239b340301060d8155a0020a0000000207867cea37010b06836bc00905060101000001836abc570a0300000000001680228f7d0703030000108400ac050703000002168302853b08000103000100068418c6790602010002020017865793550603001c803d84280d00000001000011850c812901168671af190a01010004000783159302060029850a6102081f8718ee2b010703218544d150040b0008835680790607020200804c8d43010f27870b9069030d00218168a83f0117857fe51c06080102001c80248c6b070604001c8526a136060308188607ad41030d010c8576ca010d03000102088545b84a050d0000002e805e934e020a0500078539a877040003092a825e977203040102348342bc010408020101000000198622e778010d000017801582190300000802822b833a07020003000000000000338702ca070108000000002c806c957307000001000100000000028350c36105000200000200002b8315a53205020000000001002000"_hex_v_u8, {{1344, 184}, {14532, 3445}, {2929, 1712}, {19, 378}, {-2610, 2705}, {-19575, 18795}, {-12674, 4996}, {-2889, 974}, {-4804, 1026}, {-1466, 236}, {-3905, 578}, {-4401, 592}}); - TestOptimalLinearization("8705ca08008231997201826b964d02872adf1b03807f994d0303861d9d0d01000584008f3502000281029c0703000283678c2804000104860ad4540500010480308a0e030580028e0d00108266a15d070000048134826d06010e8576806b0600000f82098f6a0a0000000c821e95270506088535826c060303865ca8310104147e8c3b06000e832090420600020311861d995305020202018330901f05000100148511bf1d050202030002833d92660801000200028337805606060000001380528f6206020301000007830cac650406000117813698660a00020000000000000683688f1c04020006000011814b8e63020614857592200c010000000007810f872e05080000028634ac16020c1980148e2800288309893f09050001000000028704af74012a8546a0300c010201000381658c090401288068905e0201278135956303070100010026855aab5109020200000000000016813d933d030402041d874bb051030a0000158577650501040300000009817f9c1e0205030c84419f6c0502040001000d8457d22c03030600001c8033883c0205041e80698b0e080202010000000c84058726010801278222876e0c0000000100000001871c820001080100208747e02f030100000117864585210003001084789b5a0002002200"_hex_v_u8, {{4804, 1029}, {1721, 433}, {-813, 15413}, {-1617, 12598}, {-7653, 3678}}); - TestOptimalLinearization("873b94550082209e2201835ac664028740b35703806d82630480568177056e83670683069c77078058920108855a974909871cf6520a821c912d0b820595650c8560864a0d844f86290e801790420f843280631080799b7e11812b9209128742a66c138674d41214807e281583309615168444881917844fd17c188356c12b19810681070000000000000000000000000000000000000000000000000000198240a9580100000000000000000000000000000000000000000000000000188707ea160200000000000000000000000000000000000000000000000000188471931b030000000000000000000000000000000000000000000000000014788a6d040000000000000000000000000000000000000000000000000014864a98300500000000000000000000000000000000000000000000000000128733ca0206000000000000000000000000000000000000000000000000001284099c5b07000000000000000000000000000000000000000000000000001283499319080000000000000000000000000000000000000000000000000012805487620900000000000000000000000000000000000000000000000000128051820c0a0000000000000000000000000000000000000000000000000010823f87730b00000000000000000000000000000000000000000000000000108366ae390c0000000000000000000000000000000000000000000000000010815180370d0000000000000000000000000000000000000000000000000010810692790e000000000000000000000000000000000000000000000000000c855ec0220f000000000000000000000000000000000000000000000000000c82269f2010000000000000000000000000000000000000000000000000000c824ab42811000000000000000000000000000000000000000000000000000c853f825b12000000000000000000000000000000000000000000000000000c833db84713000000000000000000000000000000000000000000000000000c81028c6214000000000000000000000000000000000000000000000000000c8272943b150000000000000000000000000000000000000000000000000008821191781600000000000000000000000000000000000000000000000000068057963317000000000000000000000000000000000000000000000000000684768176180000000000000000000000000000000000000000000000000005807182601900000000000000000000000000000000000000000000000000058309ac2a1a0000000000000000000000000000000000000000000000000005846acb461b00000000000000000000000000000000000000000000000000058564a1251c00000000000000000000000000000000000000000000000000058446a5791d00000000000000000000000000000000000000000000000000048142917a1e0000000000000000000000000000000000000000000000000004830898781f00000000000000000000000000000000000000000000000000048150a17120000000000000000000000000000000000000000000000000000100"_hex_v_u8, {{4594, 602}, {1855, 249}, {1121, 151}, {5310, 719}, {7657, 1052}, {5449, 1012}, {2001, 416}, {2550, 1090}, {18542, 18063}, {240, 241}, {198, 209}, {187, 758}, {-92, 337}, {-238, 831}, {-132, 262}, {-570, 447}, {-1294, 753}, {-1293, 585}, {-2195, 868}, {-1374, 498}, {-1902, 649}, {-2493, 710}, {-1277, 262}, {-3037, 614}, {-759, 120}, {-3684, 573}, {-2233, 336}, {-1498, 215}}); + TestOptimalLinearization("826db830008414a23c01744d028723d67e0103845cb0480201846ca1060202802d8b0e030104852dc545040104800e825f040283548424000f830aba39010a8241991402068612d67503030d8360b66301108712eb58070003843b905805040d8449865e05000b8503cd1908040003825ca40b03060204844b8a3c03030313852e8456030404000c834c9d1107000103000b8717b2590a00000200000b8035901106030003000f810c8a1c0a00000003000f862ea7130608000b816aa87706040400188112905b05070a8327bb040d02000000000d844cce410a05010009807994720502040e803c84690a0202020000058061813301050520800e8d6f0906010000001c84288f45090204000100001f820aa37607020206000d8073857c0602091f8539c4120602020502001a8728c826050c01078364c673060c0106832da9030b02020300000000286c877903040a00258466be7b050606000020840e9b7105010a23815f9321080300040002000000867fdf300500000a02002285168b50060008000100010123841ac7210704000200000101001c834d816706020302020000000022845ace070505000000010000000f81419e650207000002002c844eb3520b0000000100000000001582129f1c0b000000020000000008807b98060a0200020000000000038011825908010102000000000100001580378e3006040200000000038561ac27030103020e82459c170002000202000b8336a9420203000000000000000f00"_hex_u8, {16, 36, 20, 46, 57, 32, 18, 42, 53, 56, 1, 17, 7, 26, 22, 2, 27, 34, 29, 24, 40, 39, 25, 41, 35, 23, 19, 9, 44, 52, 49, 13, 5, 50, 28, 51, 31, 10, 0, 4, 11, 15, 38, 33, 3, 48, 8, 55, 30, 12, 14, 54, 58, 37, 21, 6, 43, 45, 47}); + TestOptimalLinearization("823f9b1b00864fa2680182328c07028017890c02038607d0770105864dd04a0205852f80020108801e8c6c0208840aac1c050006813f9b0e010e826b9340040006806b856006000969823108000000870bb1230403010c837cb754040502867f934c0600010983388872050100088549c578060001010f861b812304040109872daf3004050109841f8a3208010100000a86008b0d04000407824ea36902090015850f802d01081881068d7f0501000310862fab02000915827e961f0308000011855ac76f030405028668b31a0202061c8602a81b020700001e82029017010a8351af460105000009801b866601030300010e837aa96602030200010e8420af76020400000008850fb76701000201000014861fc37804000100001000"_hex_u8, {31, 34, 24, 13, 27, 6, 16, 12, 2, 32, 25, 10, 9, 8, 23, 17, 26, 18, 30, 3, 35, 5, 22, 14, 7, 1, 36, 21, 19, 4, 11, 0, 29, 20, 28, 33, 15}); + TestOptimalLinearization("8365c026008371c34b01841bc8160284789d30038141a3160486478906058645803806855f977d078175a27308831dab3e0986188b780a8031876b0b8539c1050c8708ea770d825b88020e82588c000f814d9f59108560de11118643c124128058856b13833da2251483229a35158723cc5116800e80241780108e5418807e9432198269a64c1a855cb10d1b82628d431c834cb73600000000000000000000000000000000000000000000000000000000001d8545a35601000000000000000000000000000000000000000000000000000000001c866bd03002000000000000000000000000000000000000000000000000000000001a8251a152030000000000000000000000000000000000000000000000000000000019847d8c2104000000000000000000000000000000000000000000000000000000001887129a26050000000000000000000000000000000000000000000000000000000017840b8517060000000000000000000000000000000000000000000000000000000015857c9c7f0700000000000000000000000000000000000000000000000000000000148608860d080000000000000000000000000000000000000000000000000000000013855d987a0900000000000000000000000000000000000000000000000000000000128461a33f0a00000000000000000000000000000000000000000000000000000000128701e97a0b0000000000000000000000000000000000000000000000000000000010820e84790c00000000000000000000000000000000000000000000000000000000108521d6290d00000000000000000000000000000000000000000000000000000000108406bd0e0e000000000000000000000000000000000000000000000000000000000d850e9f140f000000000000000000000000000000000000000000000000000000000b8424b46510000000000000000000000000000000000000000000000000000000000a830e9c6e110000000000000000000000000000000000000000000000000000000009850d894912000000000000000000000000000000000000000000000000000000000881308b0c1300000000000000000000000000000000000000000000000000000000058273a1581400000000000000000000000000000000000000000000000000000000048426cc27150000000000000000000000000000000000000000000000000000000002817f9964160000000000000000000000000000000000000000000000000000000001873ad510170000000000000000000000000000000000000000000000000000000001816f832a180000000000000000000000000000000000000000000000000000000001874aaf1c19000000000000000000000000000000000000000000000000000000000100"_hex_u8, {8, 4, 44, 1, 46, 17, 47, 34, 6, 29, 28, 19, 10, 42, 12, 13, 54, 36, 22, 40, 49, 38, 41, 23, 15, 31, 27, 3, 32, 24, 30, 0, 5, 51, 7, 50, 45, 37, 53, 2, 33, 43, 20, 11, 52, 18, 14, 39, 25, 9, 16, 21, 35, 26, 48}); + TestOptimalLinearization("8741984d008704eb3f01815799390281319457038626a424048661dc1705861fbf1106814685750782448178088331af0c098525ae120a8662aa220b816d450c8210a2430d870e9a160e804692290f845690751081158744118029844312871ac2091381589435148520ad471580548441168512d313178422b948188647b82e198267a50f1a81479b4d1b815c8c291c8640a8031d851faa720000000000000000000000000000000000000000000000000000000000001d813587770100000000000000000000000000000000000000000000000000000000001d84268e170200000000000000000000000000000000000000000000000000000000001a815f99300300000000000000000000000000000000000000000000000000000000001783569c6c04000000000000000000000000000000000000000000000000000000000016850fa31c05000000000000000000000000000000000000000000000000000000000015833eac460600000000000000000000000000000000000000000000000000000000001081589c4e0700000000000000000000000000000000000000000000000000000000000c805395560800000000000000000000000000000000000000000000000000000000000b817a83730900000000000000000000000000000000000000000000000000000000000a807e8e530a00000000000000000000000000000000000000000000000000000000000a842ac5360b000000000000000000000000000000000000000000000000000000000009803388160c00000000000000000000000000000000000000000000000000000000000785069b4d0d000000000000000000000000000000000000000000000000000000000007831b9e0b0e000000000000000000000000000000000000000000000000000000000003803989220f0000000000000000000000000000000000000000000000000000000000038663ca511000000000000000000000000000000000000000000000000000000000000383789013110000000000000000000000000000000000000000000000000000000000028418907f1200000000000000000000000000000000000000000000000000000000000286178422130000000000000000000000000000000000000000000000000000000000028072935e140000000000000000000000000000000000000000000000000000000000018222825e1500000000000000000000000000000000000000000000000000000000000000"_hex_u8, {38, 15, 39, 16, 17, 7, 24, 21, 13, 18, 11, 0, 23, 34, 26, 48, 50, 33, 31, 28, 9, 5, 4, 40, 44, 19, 8, 22, 3, 37, 27, 32, 25, 49, 20, 10, 42, 1, 35, 12, 14, 51, 47, 29, 6, 46, 45, 2, 36, 41, 30, 43}); + TestOptimalLinearization("814e9f7400857edb66018043813402821fa96e038608bd4c048348bc2d05815ca33c06833387610780068b7408842ca841098059823d0a835382320b85418e4b0c84079d380d814b93520e83218a1a0f816b83491084088a4f11802e910512810a8e67138418c1541480408b2715845aaf6d1682529e5c000000000000000000000000000000000000000000000016837e88730100000000000000000000000000000000000000000000148733ce200200000000000000000000000000000000000000000000118279913c0300000000000000000000000000000000000000000000118276af0204000000000000000000000000000000000000000000000f80598c2405000000000000000000000000000000000000000000000f8734e31706000000000000000000000000000000000000000000000e804b803507000000000000000000000000000000000000000000000a85308b320800000000000000000000000000000000000000000000098418c039090000000000000000000000000000000000000000000008852898740a0000000000000000000000000000000000000000000006807596680b000000000000000000000000000000000000000000000585389e3e0c00000000000000000000000000000000000000000000058612cd260d00000000000000000000000000000000000000000000048338a41c0e000000000000000000000000000000000000000000000486068d430f0000000000000000000000000000000000000000000004806595121000000000000000000000000000000000000000000000038719de681100000000000000000000000000000000000000000000038301ab6912000000000000000000000000000000000000000000000380158b2b1300000000000000000000000000000000000000000000038138844b1400000000000000000000000000000000000000000000038465cb1615000000000000000000000000000000000000000000000386768e491600000000000000000000000000000000000000000000028072920f17000000000000000000000000000000000000000000000200"_hex_u8, {10, 2, 5, 42, 0, 14, 6, 23, 21, 25, 3, 18, 26, 11, 17, 28, 19, 35, 16, 45, 46, 31, 7, 41, 29, 36, 12, 37, 32, 8, 1, 33, 13, 30, 9, 27, 22, 20, 43, 4, 34, 40, 44, 39, 38, 15, 24}); + TestOptimalLinearization("84648d7e00851fb02200018604a232010185649025020084139c5b0300863fc31200000384248d2d010003843d822e020002816f9c360400018432830704000009851fa258060000048045826d060001008618c665070000000881138c4305010008825497140305038263985006030002845e9d0404030000000c8140884a010402000986549e79030401000380198b7c03030001011382409164060300000011831598630701000000001181778c2b070200000000000f82118565040005098464b735040300000000007b8863010501001181229368020501000e82039006000300038014817f010001000000000003804e8d080100010000001b00"_hex_u8, {7, 1, 6, 12, 25, 18, 20, 16, 24, 21, 22, 27, 0, 19, 10, 15, 3, 14, 4, 23, 17, 13, 5, 29, 8, 11, 9, 2, 26, 28}); + TestOptimalLinearization("6f856d0087059a220172853002813d9a2c038730867604803d820c05842e9b53068066806e07873bb577088146922009847891710a865ba91f0b8018825d0c807e8b550d803789560e810e9c370f8361a271108455c650118440c30b1282068341137f8939148010841515802d917b168736c03217871f801718847ac31819805a211a82569d310000000000000000000000000000000000000000000000000000001b803a916b01000000000000000000000000000000000000000000000000000019836d912a0200000000000000000000000000000000000000000000000000001980348345030000000000000000000000000000000000000000000000000000168124804004000000000000000000000000000000000000000000000000000016843eb63705000000000000000000000000000000000000000000000000000015856c932a0600000000000000000000000000000000000000000000000000001580068a6507000000000000000000000000000000000000000000000000000013801f844408000000000000000000000000000000000000000000000000000012824cb6070900000000000000000000000000000000000000000000000000000f802c8a430a00000000000000000000000000000000000000000000000000000f8477d0400b00000000000000000000000000000000000000000000000000000e8319bf140c00000000000000000000000000000000000000000000000000000d816e9a2c0d00000000000000000000000000000000000000000000000000000d835c886b0e00000000000000000000000000000000000000000000000000000d81709c680f00000000000000000000000000000000000000000000000000000d821f9f161000000000000000000000000000000000000000000000000000000c802582151100000000000000000000000000000000000000000000000000000b84488b0b1200000000000000000000000000000000000000000000000000000b81679e591300000000000000000000000000000000000000000000000000000a8741c4261400000000000000000000000000000000000000000000000000000a805c975b1500000000000000000000000000000000000000000000000000000a7b8946160000000000000000000000000000000000000000000000000000068255820717000000000000000000000000000000000000000000000000000006810b8178180000000000000000000000000000000000000000000000000000068656ac4419000000000000000000000000000000000000000000000000000005810180081a0000000000000000000000000000000000000000000000000000058447a3081b000000000000000000000000000000000000000000000000000004864e960b1c0000000000000000000000000000000000000000000000000000038273a1501d0000000000000000000000000000000000000000000000000000038304a6161e00000000000000000000000000000000000000000000000000000282189d3e1f0000000000000000000000000000000000000000000000000000018338b83820000000000000000000000000000000000000000000000000000000815f92662100000000000000000000000000000000000000000000000000000000"_hex_u8, {39, 56, 6, 51, 18, 30, 5, 2, 10, 14, 7, 54, 58, 41, 23, 19, 46, 13, 20, 25, 16, 35, 1, 42, 40, 32, 49, 26, 24, 59, 43, 29, 31, 55, 57, 27, 53, 37, 60, 50, 47, 17, 4, 12, 45, 9, 48, 44, 28, 34, 33, 52, 8, 0, 22, 11, 15, 36, 3, 38, 21}); + TestOptimalLinearization("832a8e4f008160850201854bbe4e0283429e1e0382558b2404872c937d05831593610672801d0780088b0c088708a5330982159d510a865db6010b83618d160c8526b8030d824f89520e813090590f80598d62108637b42a1181348e6d12863eb44a13863bc76d1483329779158543b65816813d9a141781198f4618810d934d00000000000000000000000000000000000000000000000000188319ad1601000000000000000000000000000000000000000000000000188634c8740200000000000000000000000000000000000000000000000017826087340300000000000000000000000000000000000000000000000011830d82050400000000000000000000000000000000000000000000000011860b8356050000000000000000000000000000000000000000000000000e807c9141060000000000000000000000000000000000000000000000000985349100070000000000000000000000000000000000000000000000000100"_hex_u8, {13, 30, 5, 23, 29, 32, 24, 26, 6, 7, 18, 20, 3, 10, 8, 0, 14, 9, 28, 25, 17, 21, 19, 15, 27, 2, 4, 31, 11, 16, 12, 22, 1}); + TestOptimalLinearization("806c883b00852cb52d0184028f590285248a01000584149e6d0203872de672040284648f2905028554b02800000b8637b471010006860ca51a0402028405a80706000009842ebb39020307845d814d03030006817da346040300058453a9760700010003835c8f680309804a8f0e070200108739ae4c070200010580588310090002000382738e6f090200000c8559c940040501000d87198e190005188417a5560202040e816e803203010600098112956402031d8450a5700a000000000100188117981f0b00000000010013820ba5100406021a8311b240080201000101188060933d0106011b846dc679050301030b840db86c000b0b83619c26080003000000000e842a93440c0000000000000000068675cf6a070005000000001d817b92730307000000178608ac780401001384158255070301000000128449b62709000000000100108124824f020800001e82059501000201000000002281398258020100000001000e00"_hex_u8, {15, 25, 31, 9, 41, 12, 33, 40, 30, 3, 36, 38, 22, 16, 39, 34, 19, 11, 32, 17, 4, 20, 1, 2, 37, 18, 23, 35, 13, 5, 8, 0, 26, 29, 28, 10, 7, 21, 14, 24, 27, 6}); + TestOptimalLinearization("853d9a0300872ce27c01855dc769028042831b0380268234048670b972058159931a0109815b9c66040782548d5d000b8263ab21020a805f86510401088261ab3b06000204811e816802060a8070805704050a8701ad740501010c852fb83f09000001000880538b4c0305048510c24904000a85479a3b030302128413b0290207078409aa5d060500000480518a4103090a805f8413080500000009841ead02040f80058173001b842d802d0903000002098448a96004030617841aba6a09000012835c950c030b011783099f700211840eb8440502080d810e8f79040a010f81588229020704058040080500050302068619a95d0d0003000000068440a122060a010000068518a070030a04248177957b05090104855cca650802040420830c850508050401010d8348a8690206022e71871f000104020728870ec35d020001000000000200"_hex_u8, {19, 42, 39, 4, 31, 2, 16, 26, 12, 13, 11, 10, 5, 30, 17, 9, 35, 22, 14, 15, 6, 37, 24, 34, 25, 29, 21, 18, 7, 36, 27, 32, 38, 0, 23, 28, 33, 20, 41, 3, 8, 40, 1}); + TestOptimalLinearization("80278170008458b93c01840e9c220284358d1b0377800c04871ca3470580338c00068219a40807861f9b4f088200977309810a847c0a82398b2e0b814e9b760c8177915c0d8657a5360e872ba73a0f81290810847db55111854cae4300000000000000000000000000000000000012852bbb420100000000000000000000000000000000001181168d270200000000000000000000000000000000001186049933030000000000000000000000000000000000118304a5550400000000000000000000000000000000000f8338926b0500000000000000000000000000000000000f853c830e0600000000000000000000000000000000000f8530ba630700000000000000000000000000000000000f853191580800000000000000000000000000000000000e870d85570900000000000000000000000000000000000b827e83180a00000000000000000000000000000000000b874abd420b000000000000000000000000000000000008803689030c000000000000000000000000000000000008826287720d000000000000000000000000000000000007836daf3b0e0000000000000000000000000000000000078678ba550f000000000000000000000000000000000006855e877610000000000000000000000000000000000006815385071100000000000000000000000000000000000681200d120000000000000000000000000000000000058350af75130000000000000000000000000000000000028713db5e140000000000000000000000000000000000008257813b1500000000000000000000000000000000000000"_hex_u8, {18, 30, 5, 15, 32, 6, 33, 34, 26, 23, 1, 13, 36, 11, 19, 14, 20, 37, 38, 2, 21, 12, 24, 28, 17, 9, 31, 39, 16, 29, 4, 8, 3, 22, 0, 27, 10, 7, 25, 35}); + TestOptimalLinearization("825a8f49008163894a018617c37e028211980d0380649505048345b34905805f976006864f840e07856bde290885638c5c09866bee300a8171805e0b8735db090c8564c6010d8117947d0e841abf260f81209259108559917811814789531284109f4d138325b5191480528b3a158401bf7616864aae10178554db4318800d856719871cc20b00000000000000000000000000000000000000000000000000001a843a994e01000000000000000000000000000000000000000000000000001981339d580200000000000000000000000000000000000000000000000000198644d25103000000000000000000000000000000000000000000000000001980468724040000000000000000000000000000000000000000000000000019810a8d390500000000000000000000000000000000000000000000000000198446b2120600000000000000000000000000000000000000000000000000188575c56f070000000000000000000000000000000000000000000000000017813a880e080000000000000000000000000000000000000000000000000014811f832409000000000000000000000000000000000000000000000000001481289f620a0000000000000000000000000000000000000000000000000011836ab4600b000000000000000000000000000000000000000000000000001186119c020c00000000000000000000000000000000000000000000000000118673b5060d0000000000000000000000000000000000000000000000000010845c93070e000000000000000000000000000000000000000000000000000d804b856b0f000000000000000000000000000000000000000000000000000d857d835d10000000000000000000000000000000000000000000000000000c81469a5e11000000000000000000000000000000000000000000000000000981548a511200000000000000000000000000000000000000000000000000088661c1371300000000000000000000000000000000000000000000000000088119867b1400000000000000000000000000000000000000000000000000088467cb101500000000000000000000000000000000000000000000000000068526a4451600000000000000000000000000000000000000000000000000068278aa281700000000000000000000000000000000000000000000000000068329973818000000000000000000000000000000000000000000000000000582688425190000000000000000000000000000000000000000000000000005853988131a0000000000000000000000000000000000000000000000000005862098561b00000000000000000000000000000000000000000000000000038222a55c1c00000000000000000000000000000000000000000000000000038166a4101d00000000000000000000000000000000000000000000000000028730ef3b1e000000000000000000000000000000000000000000000000000183798e511f0000000000000000000000000000000000000000000000000001836d907620000000000000000000000000000000000000000000000000000000"_hex_u8, {24, 16, 49, 32, 9, 48, 52, 7, 35, 22, 17, 25, 39, 1, 57, 40, 11, 33, 31, 29, 26, 13, 12, 44, 54, 18, 19, 53, 41, 3, 51, 20, 43, 34, 8, 23, 45, 5, 2, 21, 14, 58, 50, 15, 30, 46, 47, 56, 27, 38, 28, 36, 42, 6, 0, 37, 10, 4, 55}); + TestOptimalLinearization("83158670008454b00201853eae2100038357ac07010384369d5c02028429822b0007801e887b010482216f050001800a877a0600008603a0410403800c873105000c8559ab0c040886199159070001038374b0290103108050807c0205010a830cb359040003010e8413926f04030107807c85220703000000058631af6009000001000a8637a46305050185609360070102000110846cc57b08020100000d6587160805000a8240a87007020201158551874806040101128177974c03080d84368c5f060400041a8559905a040204000c8422903002070513850ead0c09000401001d853dbd51070202020101018574d03d060009001c8104885e0c0200010103867b853c050007010b8158803c00090301118019847605060001000100038361ae5807020202000000058566ac5a0401040100010101835b854f07010000030001098237a37c0402010002001986608e5102040102001f855da12f0201000000010000"_hex_u8, {32, 20, 23, 26, 16, 33, 29, 10, 37, 7, 14, 18, 27, 13, 30, 24, 6, 8, 11, 2, 21, 40, 0, 25, 1, 28, 19, 38, 17, 22, 36, 12, 4, 5, 15, 34, 35, 39, 31, 41, 3, 9}); + TestOptimalLinearization("8711d24400834a8e460180458b4302841fbf3200028025883800068672d2640104841fc210020104856fbd3001078039820e050000018175930b03038174915d070000008469864b011086248a4004098475a8040701000a844e925c080000000d8157a0540302108442c13504020f8162895105020685169902050401128559c2360101020b81568a5207000300028427c340060500001180118d520400000204137a835c0901010001118318ad6606010204000a847c8f39050805835da52600248455cb19050206048400b27b010c048604b97b0302080a842695560024835f96790002158530bc2f030703038365a02f012d807481580800040003001c801e851e01218631a40503050004218535c7030405000413800e82080202040602846ec55f09020002000000000017831fb37904020104000000001f85588150030005010101000885449c3d0600010400000f872e8f3f080101000100000e804a825106000100011e81619a5c03010200000c80118b1301010102002c00"_hex_u8, {15, 28, 36, 20, 26, 22, 3, 24, 18, 4, 35, 11, 27, 0, 42, 6, 14, 12, 45, 40, 25, 30, 37, 7, 17, 9, 8, 33, 13, 32, 1, 21, 46, 41, 44, 29, 43, 5, 23, 38, 16, 19, 39, 34, 31, 10, 2}); + TestOptimalLinearization("845c9571008502c1220180458c6002822dae760381738272048546dc02058710ac1606826c9a240780108c6d088563b973098261b34a0a8625b4170b8532b2110c8376813d0d8424c34c0e8031911a0f81179d031081308c0911872abb6b128670a65813853ab85c148678f60a158672f17316843ba46617865d8214000000000000000000000000000000000000000000000000188537bd66010000000000000000000000000000000000000000000000188669c638020000000000000000000000000000000000000000000000188343b60c03000000000000000000000000000000000000000000000018835bb632040000000000000000000000000000000000000000000000188303b4090500000000000000000000000000000000000000000000001783039c2e060000000000000000000000000000000000000000000000178455c17207000000000000000000000000000000000000000000000016802f8b16080000000000000000000000000000000000000000000000158619a50309000000000000000000000000000000000000000000000014837db56e0a000000000000000000000000000000000000000000000014866897370b000000000000000000000000000000000000000000000014843f87570c0000000000000000000000000000000000000000000000148651ca440d000000000000000000000000000000000000000000000014863cde0f0e000000000000000000000000000000000000000000000014820990560f000000000000000000000000000000000000000000000014820a826710000000000000000000000000000000000000000000000013798c281100000000000000000000000000000000000000000000001182039f0212000000000000000000000000000000000000000000000010833dbc42130000000000000000000000000000000000000000000000108377a51b1400000000000000000000000000000000000000000000000e83649e3a1500000000000000000000000000000000000000000000000d870beb4f1600000000000000000000000000000000000000000000000b83008d401700000000000000000000000000000000000000000000000b842dc51c1800000000000000000000000000000000000000000000000b8359c5141900000000000000000000000000000000000000000000000b835bbe521a00000000000000000000000000000000000000000000000a8255876b1b000000000000000000000000000000000000000000000007824b97161c000000000000000000000000000000000000000000000007834ca4411d0000000000000000000000000000000000000000000000058673a6301e00000000000000000000000000000000000000000000000287218e731f000000000000000000000000000000000000000000000001835e8d622000000000000000000000000000000000000000000000000000"_hex_u8, {51, 12, 22, 31, 42, 41, 8, 50, 10, 25, 55, 23, 49, 20, 39, 5, 46, 33, 47, 34, 29, 28, 43, 53, 38, 24, 27, 40, 37, 3, 9, 4, 14, 26, 17, 1, 2, 11, 7, 45, 32, 19, 52, 36, 56, 0, 21, 16, 54, 44, 15, 13, 30, 48, 18, 6, 35}); + TestOptimalLinearization("805683130081759877018501ac560282608b1e038703b72f048554861d058445a50606856db672078359a70f08864abd4f097e86010a806d82030b82048b470000000000000000000000000c8712ce7e0100000000000000000000000c8470947b0200000000000000000000000c840e9d100300000000000000000000000b84539e0e0400000000000000000000000a8613b00b0500000000000000000000000a8346863906000000000000000000000009863ac27507000000000000000000000006870ebe7f08000000000000000000000005860d842109000000000000000000000005845589030a000000000000000000000002845588460b00000000000000000000000180198b490c000000000000000000000001812b972b0d0000000000000000000000008328a3770e000000000000000000000000872fa0700f00000000000000000000000000"_hex_u8, {17, 8, 14, 10, 12, 24, 3, 11, 21, 19, 18, 5, 1, 4, 6, 27, 22, 16, 9, 20, 2, 0, 7, 15, 26, 13, 25, 23}); + TestOptimalLinearization("8327982d0080608f67000085299d2a0100847b8207020082769438030082479f0b0202822a996a01000887298a350100098432a61f010883029b5b04000006870ec96a03048172812b03010008824d916f010102000c833aa8040110801a847f0402000002832c862104000000000a873d9c060202010383208e7803010110815d1101041268870f050001851254010e8124804a020411822c9028060001000e866d8a77030105836ba27e001a8503890804030116857b8f620110850ba7510008188704b103010201001c857cc54f000001000000"_hex_u8, {11, 26, 19, 21, 10, 25, 16, 15, 22, 8, 18, 14, 6, 3, 23, 1, 7, 17, 13, 24, 5, 2, 12, 28, 27, 9, 20, 0, 4, 29}); + TestOptimalLinearization("8678e51700857aca3901844ab2170282049f5f038003895f048638b6740405861f7e0208804491420206842e83130301078100901e02010b852bac6104030281759b31030301058533a67d02098275aa0108000000028178865107010001098336942a02050f841d99450305010e8501ba150304010a820b853205040a836eb53c060501057a83340904000004815e846b050416820d852b03090e845ebb310b020100000b8702835d0212815f9044000d09867ea171001e80359138020705178106880e09010000050f864fc97c040504011683109034030b010b824c8737080202000300000e847d8045090202000101000d835587720507030018862c9d00060500050b820587090608030000008461a5000103020003208601ab780106010102000183069130010305058734844f050200010100000004872fdb12050000000102000100078313ab200203020000248404a92503000101000100"_hex_u8, {39, 27, 26, 12, 36, 8, 1, 30, 7, 3, 31, 16, 28, 15, 38, 18, 10, 29, 9, 0, 24, 21, 14, 13, 4, 25, 11, 20, 2, 17, 33, 32, 42, 23, 40, 22, 19, 34, 6, 35, 5, 37, 41}); + TestOptimalLinearization("87139152008053853701864db30c0280338815038544b2040486788f4f05841e841e06862ea22907823d8f150886706f09837b872e0a830e9f7f0b8465c07b0c831eab0b0d810d825d0e832b81100f8435a76a108602b63811810f897c000000000000000000000000000000000000118445b63d01000000000000000000000000000000000011847fc24c0200000000000000000000000000000000001080558c3f03000000000000000000000000000000000010861fbd0304000000000000000000000000000000000010871fde1805000000000000000000000000000000000010815c93240600000000000000000000000000000000000f8726b74c0700000000000000000000000000000000000e817c823b0800000000000000000000000000000000000e865e8c220900000000000000000000000000000000000c8309833a0a00000000000000000000000000000000000b8000854d0b00000000000000000000000000000000000b83049e620c00000000000000000000000000000000000a82619d510d00000000000000000000000000000000000a870899120e00000000000000000000000000000000000a7d670f00000000000000000000000000000000000a8354a83c1000000000000000000000000000000000000a8159941111000000000000000000000000000000000008821da75e12000000000000000000000000000000000007807c8f6013000000000000000000000000000000000007835d840f140000000000000000000000000000000000038212a00a1500000000000000000000000000000000000383039a0c160000000000000000000000000000000000018605c2501700000000000000000000000000000000000100"_hex_u8, {41, 13, 38, 8, 0, 28, 16, 37, 26, 34, 14, 3, 25, 19, 10, 31, 33, 32, 29, 7, 4, 36, 40, 24, 30, 20, 9, 11, 39, 1, 22, 15, 17, 23, 35, 12, 18, 27, 5, 21, 6, 2}); + TestOptimalLinearization("8225830d00801c874a01832393380281088e7c038600d033048639927a0581249631068324b3150782649f4c08816840098527b34b0a802c816c0b850a8f040c866cc57e0d811b90350e801a8d5e0f80308c2710810f917011800b835f00000000000000000000000000000000000012836ebc6d0100000000000000000000000000000000001281659b6c020000000000000000000000000000000000128375980a030000000000000000000000000000000000128746857a040000000000000000000000000000000000128170960d050000000000000000000000000000000000118025825f0600000000000000000000000000000000000d810098330700000000000000000000000000000000000c8572b06c0800000000000000000000000000000000000b852da800090000000000000000000000000000000000098427a87c0a000000000000000000000000000000000009806c83380b0000000000000000000000000000000000098470bd020c000000000000000000000000000000000008852b845c0d000000000000000000000000000000000008825f6d0e0000000000000000000000000000000000078151902b0f00000000000000000000000000000000000382369d1d10000000000000000000000000000000000003835f8a7e11000000000000000000000000000000000003855f864c120000000000000000000000000000000000038640bc4013000000000000000000000000000000000003861fa83e140000000000000000000000000000000000038447ba3e15000000000000000000000000000000000003802c8e54160000000000000000000000000000000000018653d11b170000000000000000000000000000000000018638cb2518000000000000000000000000000000000000866fbb471900000000000000000000000000000000000000"_hex_u8, {37, 28, 41, 17, 9, 7, 8, 12, 27, 26, 21, 5, 29, 24, 38, 14, 10, 16, 39, 36, 22, 2, 34, 19, 15, 18, 35, 3, 32, 20, 33, 23, 4, 25, 11, 0, 30, 43, 6, 31, 42, 40, 13, 1}); + TestOptimalLinearization("813c865a0080178a6f0183449e0202836ca622038446c40d0485028e6e0405816fa17203026c865604028419c03b000e82148c0f0500098351997a070103861b9f0405020a8542a07b07010002861383700111832e89530111860a830c000c8342b138020b810e97660704000006821ba6330803000008855fc612050401000d8028915e03040308832cb03c0a020000000000048509c97d0605000100118167820f07040200086586710703010000000b85762804080104851dcd4105050217854acb3a0a0301000000000f8514976b04080c83449a100808000009874485630b000102010c85799c750d00020001001b80368d0f07030005098259a0700c00000002010a8056876b050b0000001581328a660e0000000100001b807f800405060600098569850a0307050012860a933506040003000200058463b22f09020004000000000021805188430401020602188052853305010203020204824b9e150c0001000101000000248114842c0501030101030a851d944c0503010300238449a2560a0201000000000000000023844ea548070700000000000f8277ae15020700011981479a7e070500000000000000000d81339c5a070003020000000000000016867395490702000200000100001080278938030302000100007a81150400020001318457b11200010201000002827fb116010000010000002300"_hex_u8, {18, 44, 53, 23, 13, 26, 1, 2, 9, 50, 3, 17, 43, 30, 41, 45, 16, 34, 0, 22, 47, 51, 15, 49, 31, 24, 38, 14, 28, 32, 40, 33, 4, 20, 21, 27, 37, 12, 6, 39, 11, 42, 46, 35, 10, 48, 29, 7, 8, 36, 25, 54, 5, 19, 52}); + TestOptimalLinearization("803a8f330086548209018265ac21028521bf2e0104800b844d02018321a05d0006835e933e040003835792230400048047865703068201a07d04068662a16d0308865ad476000e8431bb620200020b8264841503010c8625ba5704000209837d9d52021686378e68020e837b8174020e840e80590301060383329a4007020100118262885c0305010a834d8d2a02128133964d0600040d8437ac2a0503040005816b810705020419840cb2440d00000100000b865ad07005030003118419ae21060201030586748076060005000c80068a0e050103030006870dc31208020000020010863bc91f060100020301000a80218b4f0400020d817c8e6f080100020201000880108c4f010d1b834db0320607000017841ca15c0500040000020478853200020100000000001300"_hex_u8, {35, 2, 4, 6, 26, 10, 37, 23, 5, 27, 8, 0, 14, 25, 34, 22, 36, 19, 30, 13, 29, 3, 9, 17, 16, 21, 11, 20, 12, 1, 15, 33, 28, 32, 24, 18, 31, 7}); + TestOptimalLinearization("83049f4a0083539553018011896b02843fae55000583309e310201841ba76701028628b504010204850ea4570009820c846d030000078451a60303010006802c8877030203857a9e280304805e857005010c83798c7001050c8441811d0403018550bd5f0305008636c9210701000e846d9e1d010311821d933c06020006847e961a0503000a7a8945060200148610bf4d0115842fa97b0402040476841c010716872d28040201058631a10a0104001a81579d3a060001000100001681078c43020401011b8438844406000001000000000f83678264070000000000000c820c8800040101010017814c9103030300000011840c912200000000001200"_hex_u8, {18, 22, 26, 21, 12, 28, 25, 6, 9, 2, 11, 31, 24, 19, 17, 30, 23, 13, 4, 32, 10, 27, 8, 5, 3, 7, 29, 0, 1, 16, 20, 15, 14}); + TestOptimalLinearization("8600ce6f00678071018613875102865ed14301000384579a0c010103854cbe730201028376900f03010278810703068355833202058354ab7e03000b844b9a370402098269a4780303068300a66e020001010c8519a4670300020a84319c090600000007698027030204872ac12f05010100000782369e5106010000000f82549d5006000100000f845b9a7b0601010c8536a42e0601000b8325b33a0503010006826498040400050d80488e5702158206906e0702020b6b86170b000100088745ad1703108406aa3b03090e823b9117010b01821394500107148626c44e0b00000001000f82019f2a0103030001128153900a040401000000000d866bde1c03060000000d80548e180503020001068455a7100604010000001e867fd30e0a00020000000000058505891f060101000000000004840b9d3a0303010000000000268631bc12050100020000000500"_hex_u8, {39, 37, 26, 10, 31, 29, 2, 33, 1, 5, 8, 13, 22, 4, 36, 28, 9, 20, 7, 14, 24, 19, 25, 3, 32, 18, 11, 12, 17, 16, 23, 15, 34, 21, 27, 38, 30, 6, 0, 35}); + TestOptimalLinearization("851a8e58008454b44d01841a8c2902856eb42e0380314404841bbf4b0582368b3a068067897407823ca94d088420823a098555be160a823a87700b835086700c8350845e0d8747984d0e8137870c0f810f8006108417ab0911842fae6c1280358071138571c674148734d83f158327aa76168228892a178706d45018821e97001983479b591a826ca46b1b856daf59000000000000000000000000000000000000000000000000000000001b8428b309010000000000000000000000000000000000000000000000000000001a826f9021020000000000000000000000000000000000000000000000000000001a86729e61030000000000000000000000000000000000000000000000000000001a8643880604000000000000000000000000000000000000000000000000000000158646cc0e0500000000000000000000000000000000000000000000000000000012846e935e06000000000000000000000000000000000000000000000000000000128551884f0700000000000000000000000000000000000000000000000000000012811e9836080000000000000000000000000000000000000000000000000000000f82308c66090000000000000000000000000000000000000000000000000000000d865ea4640a0000000000000000000000000000000000000000000000000000000884269c770b00000000000000000000000000000000000000000000000000000008831d80570c000000000000000000000000000000000000000000000000000000068531b4620d00000000000000000000000000000000000000000000000000000005865e92390e00000000000000000000000000000000000000000000000000000004855f892d0f00000000000000000000000000000000000000000000000000000003863c8b0110000000000000000000000000000000000000000000000000000000038374aa22110000000000000000000000000000000000000000000000000000000381078e2712000000000000000000000000000000000000000000000000000000038153932c13000000000000000000000000000000000000000000000000000000018321ad5814000000000000000000000000000000000000000000000000000000018318ba1b15000000000000000000000000000000000000000000000000000000018469a57516000000000000000000000000000000000000000000000000000000018310854e17000000000000000000000000000000000000000000000000000000018543a57e180000000000000000000000000000000000000000000000000000000000"_hex_u8, {39, 32, 35, 18, 28, 7, 44, 12, 10, 25, 37, 19, 0, 20, 22, 14, 26, 8, 29, 6, 23, 45, 27, 2, 51, 33, 13, 9, 21, 47, 15, 42, 36, 46, 52, 30, 24, 16, 50, 11, 34, 17, 40, 41, 38, 5, 4, 31, 49, 1, 43, 3, 48}); + TestOptimalLinearization("82549265008464d27c01866ab47902837da12a0380368f74048738dc4d05842e8b3b06853dc84a078661ab22088454a16b09865f957f0a8279ab2b0b837b84050c837dc31a0d837db5180e7b816f0f8346ac4310800b883d1180148709128349a63c1380629800148638ae3f15802c8b59168223ae4117801d8e1718812f893319853bdc3b1a841caa5b1b8354aa55000000000000000000000000000000000000000000000000000000001c870abd4d010000000000000000000000000000000000000000000000000000001b85768103020000000000000000000000000000000000000000000000000000001a801c8861030000000000000000000000000000000000000000000000000000001980658e150400000000000000000000000000000000000000000000000000000019826da47005000000000000000000000000000000000000000000000000000000198100884506000000000000000000000000000000000000000000000000000000188528d056070000000000000000000000000000000000000000000000000000001880718a5d08000000000000000000000000000000000000000000000000000000178677ba060900000000000000000000000000000000000000000000000000000017815889110a00000000000000000000000000000000000000000000000000000016813187200b00000000000000000000000000000000000000000000000000000015804a800a0c00000000000000000000000000000000000000000000000000000015847a81550d0000000000000000000000000000000000000000000000000000001486799e420e00000000000000000000000000000000000000000000000000000013835cb8120f00000000000000000000000000000000000000000000000000000012865ff84910000000000000000000000000000000000000000000000000000000118403ac6111000000000000000000000000000000000000000000000000000000108656db361200000000000000000000000000000000000000000000000000000010815da06013000000000000000000000000000000000000000000000000000000108740f30c1400000000000000000000000000000000000000000000000000000010843ad1361500000000000000000000000000000000000000000000000000000010806a92421600000000000000000000000000000000000000000000000000000010874acc3017000000000000000000000000000000000000000000000000000000108001897218000000000000000000000000000000000000000000000000000000108213a100190000000000000000000000000000000000000000000000000000001085159f141a0000000000000000000000000000000000000000000000000000000e806288681b0000000000000000000000000000000000000000000000000000000c842d86401c0000000000000000000000000000000000000000000000000000000b860bb3081d00000000000000000000000000000000000000000000000000000008814ca17f1e0000000000000000000000000000000000000000000000000000000680418c4e1f00000000000000000000000000000000000000000000000000000006820e98212000000000000000000000000000000000000000000000000000000006856db851210000000000000000000000000000000000000000000000000000000300"_hex_u8, {3, 50, 39, 12, 20, 41, 48, 9, 22, 38, 17, 26, 42, 59, 1, 24, 51, 5, 47, 61, 46, 55, 44, 15, 28, 57, 60, 56, 33, 32, 11, 31, 25, 30, 36, 37, 34, 8, 53, 35, 14, 49, 43, 40, 23, 18, 45, 19, 4, 21, 16, 10, 13, 2, 6, 54, 58, 7, 29, 0, 52, 27}); + TestOptimalLinearization("863e9b20008701a22e0182579614010281579c03010381008737030180078e2603028345911504028417a101030981318d650508867b9a11070006823c924f0105058647a60b050101058579a75b07010001861bdf4c060001010c834e841d0700010106855dca03070102008633dc7f03060d8654bf39090000020c854bc4370802000103846aac180c000100018058811e03138727b30b0a0200010a845a902206050104804191120703010108844cc60f030b00188530b810090000030d8434be3403070d833fad1b00298038953206051d801a520606000f8216a05a030b218007891e020911815b9716030b0b867ab553050709802391740f030000010007817896370d010003000200168041880803080518816ea42a050902040e872d8a09080200050302000e8576960e050b010400098330bb6e0c06020200098418ad6a1002000300000000148704c07008020405030011851f8657060d040e8619be7016000101000000088559d32c0213078307891a08040a00011e8313b627010c0104001e853ad64004070300051b815d834205030c038423aa3904040701030001128155a3390f000000000500308262a43b0a000107010b8136861d0505000701010f82359b1307010005000401001e8028841605000603010200002981679d16030705000300298710cd6c080601010000000101308055803e0802040100010002001681758e2a090400010100000100258741ac0d0a00030001030000000680738e2c06020500000001001783629a68020703000001098707dd08000001030000001000"_hex_u8, {58, 32, 26, 8, 42, 13, 5, 60, 21, 12, 31, 18, 53, 6, 14, 23, 2, 11, 55, 52, 17, 63, 7, 44, 36, 33, 27, 49, 59, 43, 1, 19, 39, 41, 35, 4, 48, 29, 62, 34, 56, 46, 10, 9, 20, 61, 25, 50, 15, 37, 0, 30, 22, 40, 28, 51, 16, 24, 45, 3, 38, 54, 47, 57}); + TestOptimalLinearization("83638b0300845bac6801871ac51d028278937a036a5004855494040405814883580405872dd30f030203816f9009030301856bb80f0501000684008658030406805380100400068632a8520500010b80658e2f0403010580068a340702000002845cae500802000000806b8c350400040584319f5a0900000000086f827c09000100000184627b06000004038341844d0603000000001181208d070502000102048043760600000200000010862fad260603000000000a817786690402000003000e84059e410305020004861eb63a0401020001138016862600080486419756020500010008833ca46f04040000001182019658020000000200000800"_hex_u8, {9, 18, 4, 1, 0, 2, 7, 28, 17, 15, 20, 30, 27, 23, 19, 5, 24, 8, 13, 10, 16, 26, 14, 29, 6, 11, 25, 22, 21, 3, 12}); + TestOptimalLinearization("8015812700866ade5401811c8f7b028442ac3003866fc73d00058220984901048676c4440204813194740500057b8b1b060005845fa71e050106837bb34d060003853abd55070001008519ab1102030e824f94580602000a8405b15c0403020b806a8b78040303088724be690603020380708230080003000d851f9b5d05050000008674dc540401050011864f9652060200020110841c8a61090001000101832c8819060303000005814b9c160601010400068109885a06050002018304b203050001061686419e69020b00128638c97d0a010100000000000018856dc2060302080000028419b54c0307030781568573090300000000000000028428a7150702000100001d864db25f020207000a85409403000700000018822f920c0300010201001483409a1a0501000100000013856ac8200400010000010011803e8f620500000000000019836692540302000000208548895a00000000000c867ecc2801000000000a00"_hex_u8, {7, 34, 25, 20, 0, 14, 24, 9, 23, 15, 1, 26, 22, 3, 31, 12, 36, 35, 33, 19, 8, 28, 5, 32, 17, 11, 40, 39, 37, 38, 29, 10, 2, 4, 13, 21, 18, 16, 6, 30, 27}); + TestOptimalLinearization("8677a44400823d9b1101847c893e0102831ea2130201865b944502028560ac640301856cc01101088644cc2c0302867ea77d0008843d8949040202843a9d0307000081528f5707000005804e8c5b0403000585169c7e06000201834e8e0d0503000d835e96250500000f8628a9550104078018847d0302000201821f90780301000002000681648442030103028433976b070000000000000e844a9116040202000d82349016000880158b240600010100108006831101060001850bb04e0101010100088723835a010002010c830593360203000003811a8e150400000000001c7f8168010000001300"_hex_u8, {5, 6, 22, 1, 15, 21, 9, 19, 12, 2, 27, 17, 13, 14, 18, 4, 23, 11, 29, 28, 3, 8, 24, 16, 25, 20, 26, 7, 10, 0}); + TestOptimalLinearization("8744ad0c008552be55018377a07f02844ec32802038655a103020482109b72020006867ee92c030006847fb879040003867cc5770301098620c77d06000001834e9c6b050102831ea745070000048736e7040309854bb64e04000a82129d600303068327847c03060c81749e6a0604000c8616af13070400008062915d08010200078007880206030301823e815106000609862ab9220502178451b018080000010c82469e2a0803000001058579c33c090000020116852f8b210704000001068168a05d04070001148616c21d0801020001000e8327991f05000f8025860a0b000002010003862f8a250c00010100000b8002480a00010002000b801f877005000600011e8539be10010b011c8341b558060302000001001a83758b0c09030000000000038738d71b070500000000010000088527c943070005000001001d81789e5204060300001c850eb12a0b03000100000000058676d84b0602010103000b834aaa310202020001000100001c8425af0c0302020001000100000d8107942e02010201000200001c830f9f330000000002000012830ea4700200000000000000000d00"_hex_u8, {17, 14, 41, 27, 4, 1, 16, 39, 29, 0, 25, 20, 7, 5, 18, 44, 19, 2, 38, 10, 33, 22, 23, 45, 42, 30, 6, 37, 24, 11, 43, 21, 9, 40, 28, 12, 31, 3, 34, 35, 15, 13, 36, 8, 32, 26}); + TestOptimalLinearization("82159935008379b66e01830bae7202803d87690203826ea53b0302821a993303038408b52a0502864de64005028326bc7b050106827a9b050508842ace1c010f836f966204020865810a080106816ba5640703018270844306010301851f8e69050201000d8500866c0505000b8357ac7d040500098542881e040109822f8451050303048257985708010400028555bd29020e8116875e0603010211865c9f0906010408846db41b0206050786259654050503000011855ac662080300010100068655c91b020910830bb7540d0000020000000d8563da4d0e0000010000001481148d1f0e010000010012831193360a000004010a860ece440807000100068402b614060404020e8712da6e06080001028377997c070401040000018224a23c040800041e805f976e0c0201000200018655e22305060501088656a83c0801000401011e8248a140010a02002385633903010703011c80528207080302000200002780038e130c01000300000000268421330701020103010b800682590a0102020000001f863ca66005050202012b831fb146070300000202000024834c9f5d060003000100010d840dc01a040201010319857a8a2606010101000001000009824f814701040301136e876d05000202010000000c871cad4d0107002c803d884203000402008446cd4e0000010000000d00"_hex_u8, {31, 32, 54, 2, 29, 0, 20, 21, 26, 47, 7, 1, 37, 13, 51, 34, 14, 49, 48, 36, 27, 24, 23, 53, 28, 43, 44, 30, 52, 39, 35, 16, 19, 5, 50, 8, 11, 22, 15, 40, 25, 46, 10, 18, 12, 3, 4, 17, 38, 6, 45, 55, 33, 9, 42, 41}); + TestOptimalLinearization("8673c728008004810c01805e967802866fb254038536a93f048712a43d0584498d14068610c30a07822dac46088401a72f09860082450a8279a0490b6a853e0c817c991e0d815795060e8349c2490f7e8972108438b610118616b67f12807485361382058940148739c34615847ea91016805f8421178662d04718805b835019852b97491a857aaf401b832090231c810991491d802184130000000000000000000000000000000000000000000000000000000000001e855fb371010000000000000000000000000000000000000000000000000000000000198563b31d0200000000000000000000000000000000000000000000000000000000001980178c10030000000000000000000000000000000000000000000000000000000000198201867404000000000000000000000000000000000000000000000000000000000018873b86670500000000000000000000000000000000000000000000000000000000001382279e3e060000000000000000000000000000000000000000000000000000000000118442ae4d070000000000000000000000000000000000000000000000000000000000118707c3000800000000000000000000000000000000000000000000000000000000000f8533b9360900000000000000000000000000000000000000000000000000000000000e833d94160a00000000000000000000000000000000000000000000000000000000000e843381770b00000000000000000000000000000000000000000000000000000000000e811590520c00000000000000000000000000000000000000000000000000000000000d8729993f0d00000000000000000000000000000000000000000000000000000000000c82149f050e00000000000000000000000000000000000000000000000000000000000c8648c6740f00000000000000000000000000000000000000000000000000000000000c832fa20e1000000000000000000000000000000000000000000000000000000000000b860e862711000000000000000000000000000000000000000000000000000000000009842f923212000000000000000000000000000000000000000000000000000000000009815c967613000000000000000000000000000000000000000000000000000000000008824aad4714000000000000000000000000000000000000000000000000000000000008854c844715000000000000000000000000000000000000000000000000000000000008851da76b1600000000000000000000000000000000000000000000000000000000000781449e7517000000000000000000000000000000000000000000000000000000000002832e8d051800000000000000000000000000000000000000000000000000000000000000"_hex_u8, {3, 13, 28, 30, 12, 1, 21, 22, 40, 18, 44, 50, 4, 37, 36, 48, 11, 2, 15, 46, 49, 52, 9, 5, 34, 14, 17, 53, 47, 24, 8, 19, 33, 25, 41, 23, 29, 35, 26, 39, 10, 27, 43, 16, 38, 31, 54, 0, 45, 7, 6, 20, 32, 51, 42}); + TestOptimalLinearization("8063850a0084718e1f018627d96c028369c06503842ec7070480158a0505853fbf200683719c3e07806f906a088611df4e09816fa0570a863e94760b800485030c8307b4590d8642e7400e8459bf1d0f803461108259aa03118671ad171280708651138257907e14821986091582203b168527c013178315aa081880558e67198664c5511a872afc330000000000000000000000000000000000000000000000000000001b863b8d480100000000000000000000000000000000000000000000000000001b847f81610200000000000000000000000000000000000000000000000000001b8526852d03000000000000000000000000000000000000000000000000000018857d901b0400000000000000000000000000000000000000000000000000001884238e240500000000000000000000000000000000000000000000000000001885049c610600000000000000000000000000000000000000000000000000001880401a070000000000000000000000000000000000000000000000000000168349a2100800000000000000000000000000000000000000000000000000001581539c5f09000000000000000000000000000000000000000000000000000015810f96030a0000000000000000000000000000000000000000000000000000148406b8190b0000000000000000000000000000000000000000000000000000138005801a0c000000000000000000000000000000000000000000000000000013863c99570d000000000000000000000000000000000000000000000000000013842ea1130e000000000000000000000000000000000000000000000000000012810b8a5e0f000000000000000000000000000000000000000000000000000011861c8474100000000000000000000000000000000000000000000000000000118117903911000000000000000000000000000000000000000000000000000010850b981d12000000000000000000000000000000000000000000000000000010822d9d73130000000000000000000000000000000000000000000000000000108655c73614000000000000000000000000000000000000000000000000000010862baf0c15000000000000000000000000000000000000000000000000000010758c001600000000000000000000000000000000000000000000000000000f80739a7f1700000000000000000000000000000000000000000000000000000f8070856b1800000000000000000000000000000000000000000000000000000f837c8d4e1900000000000000000000000000000000000000000000000000000e806888691a00000000000000000000000000000000000000000000000000000b8570de661b0000000000000000000000000000000000000000000000000000098332bb0b1c0000000000000000000000000000000000000000000000000000098240ae6b1d000000000000000000000000000000000000000000000000000008861599711e000000000000000000000000000000000000000000000000000006821da71e1f0000000000000000000000000000000000000000000000000000038334af692000000000000000000000000000000000000000000000000000000200"_hex_u8, {40, 24, 5, 56, 16, 22, 18, 50, 3, 33, 53, 43, 52, 4, 49, 37, 47, 59, 13, 58, 54, 41, 44, 27, 39, 11, 10, 34, 45, 55, 31, 14, 32, 25, 38, 8, 1, 20, 26, 12, 2, 6, 7, 21, 36, 51, 29, 9, 42, 23, 28, 30, 17, 57, 15, 19, 48, 46, 35, 0}); + TestOptimalLinearization("822f8a1500813c8e2c01812b92570280708513038608a92804835ca704058668d931068417a738078402a65b08853f9749098176994f0a81438c730b8261827e0c816c816f0d831d8a450e825a901f0f8105852600000000000000000000000000000000108338ab330100000000000000000000000000000010852dbe30020000000000000000000000000000000e82419630030000000000000000000000000000000d813c867c040000000000000000000000000000000b831b9d1a050000000000000000000000000000000b84069108060000000000000000000000000000000b854b967b070000000000000000000000000000000b8031820b080000000000000000000000000000000b81518a2e090000000000000000000000000000000b83208e010a0000000000000000000000000000000a8670d4660b0000000000000000000000000000000a860dce2a0c0000000000000000000000000000000a8451c1270d000000000000000000000000000000098543b1490e0000000000000000000000000000000883609b660f00000000000000000000000000000006843da97210000000000000000000000000000000068028897f1100000000000000000000000000000000842ab52d120000000000000000000000000000000000"_hex_u8, {15, 21, 3, 8, 29, 30, 31, 7, 2, 24, 32, 28, 23, 5, 27, 19, 18, 17, 4, 26, 10, 6, 25, 14, 11, 9, 0, 13, 16, 12, 22, 33, 1, 34, 20}); + TestOptimalLinearization("8333b0280080278a4701831688680002870ecd590102866f74010581298e1203000280238a42030006648603040006850aac5b05000680048845020c8314866b000f8355b84a06000005856d814a070000058172823103020f8409b86904020c8664e05502050b824eab0501030681708f410014847dc92c090000000000018511993e0302010681548c17001a8276a87b050201000012816b933e0401030d853fa06b020604857ec0300901000000000b872dde14020700000f8252851c04000313813a8d0305000500088051816a04070000018228913a02081b8323854d002183458170050501000b8517ca10050201020015802f89210204178509c61503041682529401050102010686269150010003031a806e821c000002010204856798430100000101020e845498700104002000"_hex_u8, {27, 39, 30, 29, 6, 21, 18, 15, 3, 0, 1, 33, 37, 23, 24, 9, 22, 31, 10, 20, 16, 26, 11, 32, 4, 34, 38, 5, 13, 12, 2, 8, 28, 35, 17, 19, 14, 36, 7, 25}); + TestOptimalLinearization("810c8e3d008316881a01863fa11b02831dad01038049881804873d9a410203822e9f420302822299290204842d32040208874a8734020b80278a6b020b6884100408803b812505000e857ba64a0801000a874bc7760604088600aa69060980618e7a05060a8472a23a010b0b873bcf000604000e816d97620a01020f86409a730215872c8e22010c04801b8963010a18855c8b3f0a00010200000015864c98150701000401000a81428f60080005098458c254040601020d837cae5c04010a0c8273a56209050101000000058507b07b080200061080519068090003010100118310a0050503020000010000148727d92f0502020200001785599e740207000201000b8421905004010102010124854d8b0f00050003002200"_hex_u8, {33, 7, 35, 23, 15, 34, 29, 9, 28, 13, 10, 6, 5, 27, 30, 3, 8, 31, 20, 32, 12, 19, 18, 2, 21, 25, 16, 26, 24, 4, 22, 17, 0, 1, 14, 11}); + TestOptimalLinearization("850c8f35008651ce2f0165807a028725d844038227a4150481378e1c058729b702068279a853076f8878088239a3380981228d300a805c85710b86559b420c8653a67a0d860eac270e823d8c0a0f82539142000000000000000000000000000000000f80068543010000000000000000000000000000000f825f8156020000000000000000000000000000000d83459166030000000000000000000000000000000b84209c0a040000000000000000000000000000000b807e9509050000000000000000000000000000000a80709452060000000000000000000000000000000a70823d070000000000000000000000000000000a8301a000080000000000000000000000000000000a8168806c090000000000000000000000000000000a8120865e0a00000000000000000000000000000009801583190b00000000000000000000000000000009857ed1480c00000000000000000000000000000006806082300d00000000000000000000000000000004801f89590e000000000000000000000000000000038103965a0f00000000000000000000000000000003801d822d10000000000000000000000000000000038459a3031100000000000000000000000000000002872eaf7f1200000000000000000000000000000002854b9658130000000000000000000000000000000100"_hex_u8, {20, 6, 21, 16, 23, 10, 30, 35, 26, 4, 0, 24, 33, 3, 19, 7, 22, 28, 12, 14, 9, 1, 8, 34, 17, 25, 5, 15, 29, 18, 13, 32, 2, 31, 27, 11}); + TestOptimalLinearization("844f8835008631d1440183318e0a02801b896803863dc83402048525bb440304811a937e04000581669911040006872aaa100600058452b04607000480208c7005020681319777060200852dcc3c0701000b821ea3640801000481168f0808000201860c843204088715df6f0c00000000870ebd7b07030013816f9831021a82778d4200188018854a0c01000103825093730601011684298a2b0402070011832dad31030603098571cc760c00000001000000058704dd7b0b0000000000000000000b8257845005050000000000000000178630c00e04060000000001108435c159090101000000000100078474ba01050004068447ba4506030102000200028408490901030000000111850db1610a00020100000000001a8557c6570307000000011d8275ab4706000000010217648325010303188419801d04000600010012837ebd2202091785548e2f050000000103108028852702030001030383689059040300020102862aa26c010003000000002086199a08020003000000001300"_hex_u8, {28, 19, 25, 32, 30, 1, 2, 27, 14, 10, 22, 34, 12, 41, 33, 36, 0, 8, 17, 5, 18, 11, 35, 3, 6, 21, 7, 29, 37, 39, 20, 26, 42, 24, 38, 4, 13, 15, 31, 9, 23, 16, 40}); + TestOptimalLinearization("824b8e1200805c8610018129801f028373a87d0380767f0486319546058649b858068623a50f07871ca14908805c9121098637af790a8668d1220b6480290c801e827d0d845eb6420e857ec3680f8600c332108517857f118126880100000000000000000000000000000000000012806b917101000000000000000000000000000000000011815e8069020000000000000000000000000000000000118468a40e0300000000000000000000000000000000000d8355ae150400000000000000000000000000000000000b832c99610500000000000000000000000000000000000a8720cb11060000000000000000000000000000000000098623b37c0700000000000000000000000000000000000880668f1b08000000000000000000000000000000000008835b9813090000000000000000000000000000000000088279892f0a000000000000000000000000000000000006802488110b0000000000000000000000000000000000038337a31a0c0000000000000000000000000000000000038574aa730d00000000000000000000000000000000000100"_hex_u8, {21, 28, 29, 25, 10, 1, 4, 9, 7, 5, 31, 23, 24, 14, 12, 20, 6, 16, 27, 17, 8, 3, 22, 0, 19, 13, 30, 26, 18, 15, 11, 2}); + TestOptimalLinearization("866db148008305944a018340810400038721c963010282528f4802028532a1260301852e954c030685778653050002668530010c806a4a020c8451aa0f030102866c8e250202000b812e9071060000000009852f875105010000000d834e98750400020003814b8b63040000020007840fa646050000020001812c891d0203021082428c7606000001000d822e875d01118502bf170701000006840a8e6c050002010a820c9b1c0204107c871f030100031682259a480401000300188676815a0107128034845b03030002138458a24205000000000013861ca528050000000001048560b41e0200000101000e80618757020200001300"_hex_u8, {18, 25, 28, 22, 13, 15, 4, 6, 23, 30, 21, 29, 1, 5, 10, 20, 27, 19, 2, 17, 0, 12, 14, 7, 3, 9, 24, 16, 8, 26, 11}); + TestOptimalLinearization("8260991f008662892d0001837fa91b01008401a85d0001870cad1f0101810c8658010681356a0206846b824c0400058661c47805000183058c7104028609914d06000a864fc143070004852fb7020601078132943c03040008845eb202040201048626a67f02000682358c18040004000384249049050000030781428c4c02020c8361962f030204028078873307000001010008821b986c0205010005853b8a0e070001000000000c8260956c0301040c862ca078030000010200186b825d010401000c807d930100040101821196590500000000000000088235880e020000001300"_hex_u8, {8, 5, 10, 21, 4, 24, 26, 19, 6, 2, 7, 3, 18, 1, 11, 23, 12, 13, 17, 28, 16, 22, 25, 14, 0, 15, 9, 20, 27}); + TestOptimalLinearization("842ba05d0083138d6d018720e40a0268816b038548bc49000684269a620105840dab78030007850cc00c010009835486260200088667873a0300078065811006000103865b943f050303836db67905078749c8200700010b8742c257080001000d8351a3460500098604a67e060000108355896d0407000c8712b40005050004832e854607000400128421a30704060f8416944b020a01804e8d5207020100001081598f290209088422862b0700030306867cb04a06030100128733c8370005050e840a884d020105031b8477ba4404050100020886669d270203051886378d2e04030100020000000d8745db65020700000000198465845e0205001382059f3a07020001000000001c843ca06304060100001c854d8f670208000b81519352000004000f84598017000001000200"_hex_u8, {34, 37, 33, 23, 1, 17, 4, 14, 16, 20, 29, 10, 31, 32, 7, 24, 12, 26, 2, 36, 11, 27, 28, 3, 13, 15, 5, 22, 30, 0, 19, 9, 18, 25, 6, 21, 35, 8}); + TestOptimalLinearization("810e982400840a9a7e018619dc02028157a542038640a10b04844ec93a058055805f06872eb8660783718a1f08874bcc070980477a0a820194780b8345a66d0c8310a0420d8437b4660e8672af300f8225957310801a826f11807b877e128558d32c136e87581483299c7a00000000000000000000000000000000000000000015805f904d01000000000000000000000000000000000000000015831f922a020000000000000000000000000000000000000000158570be5d03000000000000000000000000000000000000000015863c88160400000000000000000000000000000000000000001480178919050000000000000000000000000000000000000000128563816406000000000000000000000000000000000000000012864bc86307000000000000000000000000000000000000000012841c9a7b0800000000000000000000000000000000000000001182029c6e0900000000000000000000000000000000000000000f8234922d0a00000000000000000000000000000000000000000d800582520b00000000000000000000000000000000000000000d8570cb7d0c00000000000000000000000000000000000000000c8471c94d0d00000000000000000000000000000000000000000c8013865b0e00000000000000000000000000000000000000000c83348a680f00000000000000000000000000000000000000000b811496721000000000000000000000000000000000000000000b850cd3641100000000000000000000000000000000000000000b8738905f1200000000000000000000000000000000000000000b6d812e1300000000000000000000000000000000000000000a7a81501400000000000000000000000000000000000000000a836ba6171500000000000000000000000000000000000000000a8736e1381600000000000000000000000000000000000000000a834a833c170000000000000000000000000000000000000000078340af00180000000000000000000000000000000000000000068460cd141900000000000000000000000000000000000000000686429d651a00000000000000000000000000000000000000000382179f3d1b0000000000000000000000000000000000000000038651b36c1c0000000000000000000000000000000000000000038405c04b1d000000000000000000000000000000000000000002874182401e0000000000000000000000000000000000000000028127827d1f00000000000000000000000000000000000000000100"_hex_u8, {11, 14, 7, 50, 4, 52, 38, 36, 34, 17, 41, 6, 47, 29, 16, 20, 43, 13, 42, 35, 24, 27, 40, 33, 26, 39, 15, 0, 46, 2, 19, 30, 31, 25, 5, 37, 49, 9, 51, 28, 44, 12, 18, 23, 32, 8, 3, 10, 1, 45, 21, 22, 48}); + TestOptimalLinearization("852dbb7700865eeb7601817ca676028220a65e000580368e660204850932030281369816030106872caf420208861bdc08020209861eba7403020880378d6703020b8253965b040209823f95360013826ab4040402048713bd3606010101817f88540009837cb26c060003000d81628e4e07000300058009811605000511817a9c10090002000005821e9379040700048656d7620500060b850e8d6803080008841a9f44040700138239a535060005010f842e81630605000114822a8f73040800000a8539b3580b010000028407c670020a0e811f0b050702058616cb1303081c8315ae6406040301001c806f9921020c16860fe23e040c038563cf050a0001040f8023842d020e16803f885c050700040182109c010206080d8242ae6702042c813ca3320209041f843ec61401030a1082659641080201020223864cbc42010e1e8442a279012980608866010b0010836c991e0106010f8637903f09010002001e820998050a0500000000108328b41c0200050a825a8d63000b0f827bb9030009108152923704020300020080298155060201020000048023802102093283758a2c000600010035805a8403030203218516c7410300010000000200"_hex_u8, {33, 47, 24, 27, 46, 7, 42, 18, 25, 50, 55, 29, 26, 13, 15, 41, 16, 0, 3, 52, 2, 9, 12, 28, 49, 40, 39, 45, 17, 21, 6, 32, 14, 23, 5, 31, 43, 35, 8, 19, 44, 10, 48, 53, 11, 37, 30, 20, 38, 4, 1, 36, 51, 56, 22, 34, 54}); + TestOptimalLinearization("803894000087239a23018325873d02812fa0580100028315a2570200027c8a3f0300028608b21b030102870aeb0c05000283728121060000853fcb4d070000856ddb50020b802c927803030b8361c41105030a874af55b050209814d825101168319b7420600040e752f0601030e8054947c0700000d841ca56f0409817a26080501827cb2340108020c83239b340301060d8155a0020a0000000207867cea37010b06836bc00905060101000001836abc570a0300000000001680228f7d0703030000108400ac050703000002168302853b08000103000100068418c6790602010002020017865793550603001c803d84280d00000001000011850c812901168671af190a01010004000783159302060029850a6102081f8718ee2b010703218544d150040b0008835680790607020200804c8d43010f27870b9069030d00218168a83f0117857fe51c06080102001c80248c6b070604001c8526a136060308188607ad41030d010c8576ca010d03000102088545b84a050d0000002e805e934e020a0500078539a877040003092a825e977203040102348342bc010408020101000000198622e778010d000017801582190300000802822b833a07020003000000000000338702ca070108000000002c806c957307000001000100000000028350c36105000200000200002b8315a53205020000000001002000"_hex_u8, {6, 42, 23, 38, 18, 36, 51, 50, 4, 55, 24, 52, 34, 39, 10, 25, 32, 37, 40, 35, 53, 29, 46, 17, 41, 19, 44, 54, 20, 22, 45, 2, 27, 31, 57, 13, 0, 8, 28, 7, 47, 48, 1, 5, 33, 43, 21, 15, 12, 16, 49, 26, 3, 9, 58, 11, 56, 30, 14}); + TestOptimalLinearization("8705ca08008231997201826b964d02872adf1b03807f994d0303861d9d0d01000584008f3502000281029c0703000283678c2804000104860ad4540500010480308a0e030580028e0d00108266a15d070000048134826d06010e8576806b0600000f82098f6a0a0000000c821e95270506088535826c060303865ca8310104147e8c3b06000e832090420600020311861d995305020202018330901f05000100148511bf1d050202030002833d92660801000200028337805606060000001380528f6206020301000007830cac650406000117813698660a00020000000000000683688f1c04020006000011814b8e63020614857592200c010000000007810f872e05080000028634ac16020c1980148e2800288309893f09050001000000028704af74012a8546a0300c010201000381658c090401288068905e0201278135956303070100010026855aab5109020200000000000016813d933d030402041d874bb051030a0000158577650501040300000009817f9c1e0205030c84419f6c0502040001000d8457d22c03030600001c8033883c0205041e80698b0e080202010000000c84058726010801278222876e0c0000000100000001871c820001080100208747e02f030100000117864585210003001084789b5a0002002200"_hex_u8, {1, 26, 34, 35, 33, 31, 38, 46, 19, 49, 27, 8, 5, 0, 36, 55, 4, 17, 47, 3, 18, 41, 6, 30, 37, 51, 53, 29, 15, 11, 10, 12, 50, 24, 7, 43, 16, 52, 9, 44, 28, 14, 45, 2, 48, 22, 23, 42, 39, 54, 13, 20, 25, 32, 40, 21}); + TestOptimalLinearization("873b94550082209e2201835ac664028740b35703806d82630480568177056e83670683069c77078058920108855a974909871cf6520a821c912d0b820595650c8560864a0d844f86290e801790420f843280631080799b7e11812b9209128742a66c138674d41214807e281583309615168444881917844fd17c188356c12b19810681070000000000000000000000000000000000000000000000000000198240a9580100000000000000000000000000000000000000000000000000188707ea160200000000000000000000000000000000000000000000000000188471931b030000000000000000000000000000000000000000000000000014788a6d040000000000000000000000000000000000000000000000000014864a98300500000000000000000000000000000000000000000000000000128733ca0206000000000000000000000000000000000000000000000000001284099c5b07000000000000000000000000000000000000000000000000001283499319080000000000000000000000000000000000000000000000000012805487620900000000000000000000000000000000000000000000000000128051820c0a0000000000000000000000000000000000000000000000000010823f87730b00000000000000000000000000000000000000000000000000108366ae390c0000000000000000000000000000000000000000000000000010815180370d0000000000000000000000000000000000000000000000000010810692790e000000000000000000000000000000000000000000000000000c855ec0220f000000000000000000000000000000000000000000000000000c82269f2010000000000000000000000000000000000000000000000000000c824ab42811000000000000000000000000000000000000000000000000000c853f825b12000000000000000000000000000000000000000000000000000c833db84713000000000000000000000000000000000000000000000000000c81028c6214000000000000000000000000000000000000000000000000000c8272943b150000000000000000000000000000000000000000000000000008821191781600000000000000000000000000000000000000000000000000068057963317000000000000000000000000000000000000000000000000000684768176180000000000000000000000000000000000000000000000000005807182601900000000000000000000000000000000000000000000000000058309ac2a1a0000000000000000000000000000000000000000000000000005846acb461b00000000000000000000000000000000000000000000000000058564a1251c00000000000000000000000000000000000000000000000000058446a5791d00000000000000000000000000000000000000000000000000048142917a1e0000000000000000000000000000000000000000000000000004830898781f00000000000000000000000000000000000000000000000000048150a17120000000000000000000000000000000000000000000000000000100"_hex_u8, {5, 38, 36, 56, 24, 44, 2, 41, 27, 50, 37, 35, 55, 8, 7, 0, 19, 54, 11, 25, 6, 12, 26, 40, 18, 58, 31, 4, 48, 3, 47, 30, 29, 14, 52, 34, 53, 42, 17, 13, 46, 20, 45, 23, 32, 1, 21, 9, 16, 49, 39, 15, 51, 28, 22, 10, 33, 57, 43}); // Clusters which admit repeated states in SFL. - TestOptimalLinearization("862ea341008713833c018745817502827a814f0382528b6704813381280581308548010005815a8e7a0100010684019f0005000003802783720500000009856cae0005000001028601ac0e050000000475811a0601000000008135834c070000000000088007863e0800000000000284299b710900000000000200"_hex_v_u8, {{7533, 8149}, {-1849, 681}}); - TestOptimalLinearization("82759235008069896c0186438e3d028244912600000003851ba405010000038214845c0200000183018a4b03000001807f841f00000000078573823a0100000007820f8a65020000000164805703000000018622ab5804000000018412936600000000000c82749c04010000000008832b977602000000000700"_hex_v_u8, {{694, 233}, {2856, 7908}}); - TestOptimalLinearization("85478e3b00823c904101820c893f0283179c5903814c893104854282530583429f140100000103830d8509010001000284409a70020100000181168c190300000001088718b06a0400000001058553ac2c0500000000000b8506a22e060000000000008552803a0000000008800f861e020000010008817c844802000100010700"_hex_v_u8, {{6613, 7335}, {-322, 2176}}); - TestOptimalLinearization("8146845100804b890d0186768b55028406a32f03863ca23104832f8e3b05810a892b0680358253078502ac5d08872d96700983718004000100000002018273952801010001000100097b3c02020000000100058562a14203010000000000010d8718817804000000010000000c862f956c050000000000000000000900"_hex_v_u8, {{1528, 1069}, {-5842, 9025}}); - TestOptimalLinearization("8460992400872dbd1901867fb07f02852a817d00000003852d87540100000181348f60020000018435942b03000000837f8943000000000681608e730100000005857da67f0200000005843794080300000004658217040000000086628a1500000000000b8708805401000000000a847fa32402000000000700"_hex_v_u8, {{1682, 736}, {-8507, 10189}}); - TestOptimalLinearization("81668e3500804e844f018435927302861f9d5f03846ea342010000018261897a010000018165831102000100863e895003000000078232985e04000000018606823f000001000986318a570200000009804300020100000981408323040000000885179a260400000000068510af7800000000000b8360966f01000000000000"_hex_v_u8, {{4144, 9101}, {-1528, 608}}); - TestOptimalLinearization("861e862e00851aa57f018060816b02831ba009038628b818048576b3010580072a068478911d07854fa8600003000007816d86560200000000048576b11403000000010009850aa7100300000100010782178f040400010000010280758a22050100000000000d860eb344060000000000010c8501975a070000000001000500"_hex_v_u8, {{3660, 936}, {6832, 9471}}); - TestOptimalLinearization("802e7300824b95370000821c8a5e0002827a89580102813185560201867ba17f0301810e83580000000000835d9a0c010000000087218c1602000000008458905a03000000008319937d00000000068216900801000000068677ab2a0200000005826f91710300000004864f4404000000038702ac3c00000000000900"_hex_v_u8, {{6067, 6956}, {392, 3033}}); - TestOptimalLinearization("8151801500823e835201842ba81902837b881e038674b461048676897a058369894306873e8511078514a802010001010001833a8f51010001000100078236885502000101000003872cab780300000101000381035605000000000000038123825305010000000000018152847106000000000000000100"_hex_v_u8, {{5948, 5991}, {-8330, 3591}}); - TestOptimalLinearization("6f845f008472960a01842084330286779f7903800786310481588d0505865994390683449e480100000000000387218e3a02000000000000811d22020000000100008500812a0300000000000003825e970e04000000000000028436815a05000000000000027c812e060000000000000000"_hex_v_u8, {{1477, 754}, {-526, 7248}}); - TestOptimalLinearization("83419a7b00860e9172000183289a1901018157824f020183209e53030085398e5a040081458e2d00010000068334a04c010000000005840d8f1d02000000000281398b70030000000000872f8f5a040000000000816a8070010000000b843ba5140100000109823a91680200000000078267903303000000000700"_hex_v_u8, {{2212, 8180}, {-1114, 487}}); - TestOptimalLinearization("867e816800827e9a7101811c8f470000018613905501000080708c0e020000865c963a030000873a834e0400008267921900000000000486238a5a0100000000028614914a020000000002823083560300000000008652993e040000000000813c8e03010000000a803c817601010000028507990402000000000a00"_hex_v_u8, {{3395, 9748}, {-962, 316}}); - TestOptimalLinearization("856d9d530083029d1d0186429d3f02866b927b038234947a000201835389400101028460895c0201000582128f5303000100803183290400000184358f790500010082779924060000000682416d0700000006867b9a4003000000000a83149b200100010100000482488f62020100000000000b00"_hex_v_u8, {{-524, 9354}}); - TestOptimalLinearization("8748865d0082558d3d01825d8f7a0281678623000003815e8b750100000277831e02000001873d8f3a03000000805b841f0001000682548f0b010000018376891e0200000007826d8320030000000482288b71040000000282078b0c000000000d82288e26010000000d872994040200010009800e800a03000000000b00"_hex_v_u8, {{1085, 477}, {513, 7734}}); - TestOptimalLinearization("817b8f1100832c965701811b8a4400000281418f16010002804f86370200028573941d0300028179820f04000280238743000000000006845291470100000000037f826c0200000000018602a563030000000001850d902000000000058652826301000000058673a03602000000028379970d030000000200"_hex_v_u8, {{-3780, 7686}, {-1543, 633}}); - TestOptimalLinearization("85179c690081659269018635831a02866289680385438d3704867eae70058726b035068009856307816e926001000100048742b83801000000010a822190360201000001098721b05603000000000108861db2580401000001000080758a30050000010000000d8354a334060100000000000d8629a87c070000010000000a00"_hex_v_u8, {{3064, 1022}, {11548, 10758}}); - TestOptimalLinearization("813d894b008263966701802d827f028375997a00000003861891180100000387219a68020000018462827503000001821a924504000001833a9d16000000000003810e8d2d01000000000284299632020000000001820993160300000000008656b4780000000009845c8f03010000000300"_hex_v_u8, {{7961, 7623}, {-1026, 732}}); - TestOptimalLinearization("86639b0b0084139655018156830f000002872895040100028567862f02000280468504030001830c8427040000870b987900000000000680527801000000000280148635020000000001860c952a0300000000018216867600000000098426a04c010000000481658d55020000000100"_hex_v_u8, {{-583, 8038}, {-939, 357}}); - TestOptimalLinearization("8718a9310084369903018666a2270000018207936e0100018470800102000084609c240300008324985c04000086418d2100000000000285708d7c0100000000028362875802000000000182519504030000000001854fa01a000000000b851fa3120100000008834d8b47020000000300"_hex_v_u8, {{4600, 9729}, {-804, 589}}); + TestOptimalLinearization("862ea341008713833c018745817502827a814f0382528b6704813381280581308548010005815a8e7a0100010684019f0005000003802783720500000009856cae0005000001028601ac0e050000000475811a0601000000008135834c070000000000088007863e0800000000000284299b710900000000000200"_hex_u8, {14, 2, 3, 6, 11, 10, 4, 8, 1, 12, 9, 7, 0, 15, 5, 13}); + TestOptimalLinearization("82759235008069896c0186438e3d028244912600000003851ba405010000038214845c0200000183018a4b03000001807f841f00000000078573823a0100000007820f8a65020000000164805703000000018622ab5804000000018412936600000000000c82749c04010000000008832b977602000000000700"_hex_u8, {8, 14, 6, 3, 9, 10, 4, 13, 2, 12, 1, 11, 5, 7, 0}); + TestOptimalLinearization("85478e3b00823c904101820c893f0283179c5903814c893104854282530583429f140100000103830d8509010001000284409a70020100000181168c190300000001088718b06a0400000001058553ac2c0500000000000b8506a22e060000000000008552803a0000000008800f861e020000010008817c844802000100010700"_hex_u8, {13, 1, 4, 11, 3, 9, 5, 0, 7, 15, 14, 12, 2, 6, 8, 10}); + TestOptimalLinearization("8146845100804b890d0186768b55028406a32f03863ca23104832f8e3b05810a892b0680358253078502ac5d08872d96700983718004000100000002018273952801010001000100097b3c02020000000100058562a14203010000000000010d8718817804000000010000000c862f956c050000000000000000000900"_hex_u8, {14, 5, 1, 12, 9, 8, 11, 2, 15, 7, 4, 0, 10, 13, 6, 3}); + TestOptimalLinearization("8460992400872dbd1901867fb07f02852a817d00000003852d87540100000181348f60020000018435942b03000000837f8943000000000681608e730100000005857da67f0200000005843794080300000004658217040000000086628a1500000000000b8708805401000000000a847fa32402000000000700"_hex_u8, {4, 12, 8, 11, 10, 0, 13, 9, 2, 14, 6, 5, 7, 3, 1}); + TestOptimalLinearization("81668e3500804e844f018435927302861f9d5f03846ea342010000018261897a010000018165831102000100863e895003000000078232985e04000000018606823f000001000986318a570200000009804300020100000981408323040000000885179a260400000000068510af7800000000000b8360966f01000000000000"_hex_u8, {7, 9, 11, 12, 6, 13, 10, 4, 0, 14, 8, 2, 1, 5, 3, 15}); + TestOptimalLinearization("861e862e00851aa57f018060816b02831ba009038628b818048576b3010580072a068478911d07854fa8600003000007816d86560200000000048576b11403000000010009850aa7100300000100010782178f040400010000010280758a22050100000000000d860eb344060000000000010c8501975a070000000001000500"_hex_u8, {9, 1, 14, 7, 15, 4, 11, 8, 2, 3, 6, 5, 0, 13, 10, 12}); + TestOptimalLinearization("802e7300824b95370000821c8a5e0002827a89580102813185560201867ba17f0301810e83580000000000835d9a0c010000000087218c1602000000008458905a03000000008319937d00000000068216900801000000068677ab2a0200000005826f91710300000004864f4404000000038702ac3c00000000000900"_hex_u8, {2, 9, 0, 3, 1, 7, 13, 15, 11, 14, 8, 5, 12, 10, 4, 6}); + TestOptimalLinearization("8151801500823e835201842ba81902837b881e038674b461048676897a058369894306873e8511078514a802010001010001833a8f51010001000100078236885502000101000003872cab780300000101000381035605000000000000038123825305010000000000018152847106000000000000000100"_hex_u8, {4, 6, 1, 0, 14, 10, 11, 8, 5, 2, 3, 9, 12, 13, 7}); + TestOptimalLinearization("6f845f008472960a01842084330286779f7903800786310481588d0505865994390683449e480100000000000387218e3a02000000000000811d22020000000100008500812a0300000000000003825e970e04000000000000028436815a05000000000000027c812e060000000000000000"_hex_u8, {1, 2, 8, 3, 6, 0, 5, 4, 9, 13, 11, 10, 7, 12}); + TestOptimalLinearization("83419a7b00860e9172000183289a1901018157824f020183209e53030085398e5a040081458e2d00010000068334a04c010000000005840d8f1d02000000000281398b70030000000000872f8f5a040000000000816a8070010000000b843ba5140100000109823a91680200000000078267903303000000000700"_hex_u8, {9, 2, 12, 8, 5, 1, 11, 4, 13, 14, 10, 3, 6, 0, 7}); + TestOptimalLinearization("867e816800827e9a7101811c8f470000018613905501000080708c0e020000865c963a030000873a834e0400008267921900000000000486238a5a0100000000028614914a020000000002823083560300000000008652993e040000000000813c8e03010000000a803c817601010000028507990402000000000a00"_hex_u8, {0, 3, 7, 10, 11, 6, 1, 14, 9, 8, 13, 5, 4, 12, 2}); + TestOptimalLinearization("856d9d530083029d1d0186429d3f02866b927b038234947a000201835389400101028460895c0201000582128f5303000100803183290400000184358f790500010082779924060000000682416d0700000006867b9a4003000000000a83149b200100010100000482488f62020100000000000b00"_hex_u8, {11, 5, 0, 8, 14, 12, 4, 6, 9, 1, 7, 13, 10, 3, 2}); + TestOptimalLinearization("8748865d0082558d3d01825d8f7a0281678623000003815e8b750100000277831e02000001873d8f3a03000000805b841f0001000682548f0b010000018376891e0200000007826d8320030000000482288b71040000000282078b0c000000000d82288e26010000000d872994040200010009800e800a03000000000b00"_hex_u8, {12, 2, 9, 11, 14, 7, 8, 5, 10, 3, 13, 15, 1, 0, 6, 4}); + TestOptimalLinearization("817b8f1100832c965701811b8a4400000281418f16010002804f86370200028573941d0300028179820f04000280238743000000000006845291470100000000037f826c0200000000018602a563030000000001850d902000000000058652826301000000058673a03602000000028379970d030000000200"_hex_u8, {9, 14, 2, 0, 8, 4, 3, 10, 5, 13, 1, 11, 6, 7, 12}); + TestOptimalLinearization("85179c690081659269018635831a02866289680385438d3704867eae70058726b035068009856307816e926001000100048742b83801000000010a822190360201000001098721b05603000000000108861db2580401000001000080758a30050000010000000d8354a334060100000000000d8629a87c070000010000000a00"_hex_u8, {11, 9, 8, 10, 2, 13, 12, 14, 3, 6, 1, 15, 7, 0, 5, 4}); + TestOptimalLinearization("813d894b008263966701802d827f028375997a00000003861891180100000387219a68020000018462827503000001821a924504000001833a9d16000000000003810e8d2d01000000000284299632020000000001820993160300000000008656b4780000000009845c8f03010000000300"_hex_u8, {12, 2, 4, 0, 5, 1, 7, 9, 6, 13, 11, 8, 3, 10}); + TestOptimalLinearization("86639b0b0084139655018156830f000002872895040100028567862f02000280468504030001830c8427040000870b987900000000000680527801000000000280148635020000000001860c952a0300000000018216867600000000098426a04c010000000481658d55020000000100"_hex_u8, {5, 9, 6, 3, 4, 13, 0, 11, 7, 1, 10, 8, 2, 12}); + TestOptimalLinearization("8718a9310084369903018666a2270000018207936e0100018470800102000084609c240300008324985c04000086418d2100000000000285708d7c0100000000028362875802000000000182519504030000000001854fa01a000000000b851fa3120100000008834d8b47020000000300"_hex_u8, {5, 1, 3, 13, 9, 6, 2, 12, 8, 11, 7, 4, 0, 10}); // Clusters which have lots of potential SFL states/transitions. - TestOptimalLinearization("84559211008539851b01825098430285268d1e00010181008e700100028425a22e02000005860a9c1403000005830b924004000005810d87040500000483768808060000038731854007000003862b9066000001010a83799a540100020104850c9a5702010000020482098c0003000002000002826897580400010000010000"_hex_v_u8, {{10878, 9607}, {-1772, 780}}); - TestOptimalLinearization("8657833900865d887e018043894b0287338377038624880100010001851fa82401000000038421990e02000000038723af560300000003866dae0a04000000028265860005000000028031863800000001088353a12c0101000000088630b51a02000000000003866ba1650300000000000300"_hex_v_u8, {{15815, 9911}, {-2227, 1003}}); - TestOptimalLinearization("852a9d7d008350920901825193330280691201000181428c25010001823d8d1f020000018355460300000182448c0f040000008608994d05000000843ea14a01000100078511a07001000200058737ad5802000200058569ae3f04010000026e80520401000000058509ac7605000000010400"_hex_v_u8, {{1641, 8273}, {-3040, 873}}); - TestOptimalLinearization("803a88570078825101806a88390282048777038430920a000003811b841f010000038003801c0200000006822092420300000002821a96380400000001820280110500000001806d8834000001000006871aaf2b01000000000003806a8a2a02000000000001864c9e600300000000000100"_hex_v_u8, {{4968, 4685}, {-3094, 1050}}); - TestOptimalLinearization("8437801e00845d833f01816b907800000286438821010002867cac720200028202895e030000861db23d00000000068419a47301000000048404966b0200000002812a817c000000058438824b01000004822c980e0200000286168f4c03000002860c8a5b040000008542997a00000000000a8247815101000000000800"_hex_v_u8, {{4563, 3197}, {-4405, 7734}}); - TestOptimalLinearization("8556877f0081658a7b01803865028412813e03810e816d048743b56e0581398d070680378048010100000001812e85280100000100000780018226020001000000078370891403000000000100824a994a05000000000000822c835a050000000000000980608376060000000000000100"_hex_v_u8, {{3511, 1091}, {1365, 4984}}); - TestOptimalLinearization("66844f008651aa61018409810902816f814d03823084080000000004843b8144010000000483528d16020000000082758c5403000000008342927f000000000886780c01000000088656802302000000088637b649000004855f8f4001000009815a8c5002000009814b8d240300000900"_hex_v_u8, {{292, 8437}, {-3557, 951}}); - TestOptimalLinearization("825d842900824a800401864bb0360281598d13038039835f04834a80310585568663068555862e00000000000000078552935e010000000000000785738c5c02000000000000058163864403000000000000058069837e040000000000000480708610050000000000000000"_hex_v_u8, {{3163, 971}, {1861, 6319}}); - TestOptimalLinearization("83249365008149926b01817a925202874bba1f038631ab2b0484788e55058613992d06857aa671078367883600000100000001844f916e010100010000008179867002000100000100847a90600300000000000007842c902a0500000000000004825e856b0500000000000000068016831206000000000000000200"_hex_v_u8, {{1257, 378}, {-10088, 9271}}); - TestOptimalLinearization("802488410085669221018528aa5b02800a8539038278921601000382338719010103802b8744030102842b8404050002857b886a040102864d9317050100088267920006000001806b813407000100863a5d080000000182529b23000000010000010884259254010000010100000781739540030000000000000600"_hex_v_u8, {{-125, 8361}, {-1810, 466}}); - TestOptimalLinearization("81528b45008715a71201834c8c090102802f85320202866a89320301812985680001068120817301010005837a836a020000000581448a060300000005846e6b0400000001814c9355000100000582758c5a0101000002833b872d02000000000884539c000300000000068459a140000000000b83098f5a010000000300"_hex_v_u8, {{2569, 1045}, {4798, 7773}}); - TestOptimalLinearization("8635a94d00866f9a5901847ea66802821c81640203856694370101018713b00d030001813b8b3603000000811980480400000086108960000100000881068b4301000001028033866202000001008556b22f030000000003835ba028040000000001815789540100000006823d903e01010000058629b01202000000000500"_hex_v_u8, {{2548, 766}, {-3769, 9412}}); - TestOptimalLinearization("81188d5500822c855b01821c3a02863a9117038425930d048207906f057243068235804f07853f8b16000002000108822a8a5601000100010880738e07020001000008850d8c4605010000000681038c2205010000010681628b4a050001000007840a8d440600000002000a8538986a070000000001000000"_hex_v_u8, {{1557, 7818}, {-964, 243}}); - TestOptimalLinearization("8522934b00812a8b15018610b44e0285789a1f0386509173048233901705840f914906857a924f07831d8e58020000000107860b806502000000010380328724030200000000824b5f0301010000000181518964040000010000000c816e8b24060000000000000b853f45070000000000000400"_hex_v_u8, {{3431, 912}, {-5784, 8563}}); - TestOptimalLinearization("832f8f59008730831a018022822b02801239038275987b048520a0590582448b6506826398500001010007854b971a0100020000088105894c0201000001068737992603000101000387249424040001010003815b82220500000001028706934a0600000100000d8602ae3d0701000000000c844789560801000000000100"_hex_v_u8, {{3440, 9506}, {-3039, 898}}); - TestOptimalLinearization("8458a65900850aac29018201855f02854fab75038461877504821e86330584328d3706861b8d7107844e9d2808847c9250000000030004836d8d3e040000000000098179916402020000010005825b95700400000100000000867dae5e04000000000001000a8162941e05000000000100000682628a4e06000000010000000600"_hex_v_u8, {{1940, 718}, {-1665, 9596}}); - TestOptimalLinearization("8147814100805389410185059d29028045833103850834048073883f05803580330000000106832b9f6c0101000105821c0b020000000000068519a8600300000000000484759a66010000018339a07201000001854ea048020000018730ba160400000086409d3c040000000c00"_hex_v_u8, {{12873, 8672}}); - TestOptimalLinearization("8219866f008118842f01854ba30b0283058a1f038614921b04866a807005840f9b140000000000000584339d1601000000000004834d925402000000000004811d8b3403000000000003844f8552040000000000038217821e0500000000000100"_hex_v_u8, {{1429, 7313}}); - TestOptimalLinearization("8177892100831b9b490181418f05027d803603872c8040048438837805852ea30200000000000006871e956c01000000000005824c9036020000000000018471972203000000000001865d8e28040000000000008566a4100500000000000000"_hex_v_u8, {{6781, 8064}}); - TestOptimalLinearization("8534a80f008374901f018379995e000002807a8c4201000285438d340200028019856403000282178b22040001830b930605000080608b06000000000000048621ad3601000000000001842ba10a02000000000000825494320300000000000000"_hex_v_u8, {{9556, 6553}}); - TestOptimalLinearization("81398a1700805f84750183639f61028032835f0387498f1b048526992b0581688f4e0000000000000480028348010000000000038005821c02000000000003864fad6803000000000003816c9156040000000000038715b5320500000000000000"_hex_v_u8, {{3013, 6235}}); - TestOptimalLinearization("83799c23008671ad4901815c896b02854fab3303810481680000000004803181130100000003845f8743020000000383258862030000000381658f6d0400000002802384590000000000058318876701000000000380758d020000038618951201000366812a02000200"_hex_v_u8, {{-7815, 6881}}); - TestOptimalLinearization("8225945300815931018413962f02836a9635038720b46d04842b840f058659974a0000000000000587179118010000000000058710a5540200000000000187169242030000000000018620ac6c04000000000001844182700500000000000000"_hex_v_u8, {{1461, 9533}}); - TestOptimalLinearization("806e801500871ca421018125845d02841a9c3703845da477048528997d058510a820000000000000068745946e01000000000004840f9b1202000000000004822d8e280300000000000484599f0004000000000004807d81050500000000000200"_hex_v_u8, {{2, 7480}, {-131, 253}}); - TestOptimalLinearization("84098a0d008000811f01812f831902867a843a038124890f04821e821905870b9e4400000000000004840aa00601000000000002852e97020200000000000284769b18030000000000018042847604000000000001853290160500000000000100"_hex_v_u8, {{7324, 7073}}); - TestOptimalLinearization("834a9b5f00820a89790180598b3f0273815703816e807004805683370580308062068417a42c0000000000000002865098610100000000000000831a93590200000000000000801981000000000a856eb5520100000786409000020000058336903803000005836b9a020400000583599c0c0500000500"_hex_v_u8, {{5272, 8022}}); - TestOptimalLinearization("85268b4c0082748120018068802102807986310381428d770480268659058340994e00000000000004806b8a3e01000000000004811f8c3c02000000000002840a8d6c030000000000018608af5604000000000001822492100500000000000000"_hex_v_u8, {{7536, 5347}}); - TestOptimalLinearization("83718f5300862d9663018700ae190281338d3303825c865104832c916705851b9c64000000000000068419a256010000000000028510a35802000000000001816b861a030000000000018564ad6804000000000001832e85480500000000000100"_hex_v_u8, {{2190, 7962}}); - TestOptimalLinearization("842a980f008356951f01805c82570282308f4303802d8317048415a13705863e51000000000000058530a15201000000000004827c865402000000000004845e93260300000000000281638e68040000000000028121832e0500000000000100"_hex_v_u8, {{-1542, 6426}}); - TestOptimalLinearization("855f8024008024816501807c81020284629b030383078631048044895c000002048078100100000000068315856a020000000004800784130300000000028167800c04000000000281758a14010000000885249a1a0100010004852ca63e020000010300"_hex_v_u8, {{3618, 5996}}); - TestOptimalLinearization("855f97230080678a4f018210925d02856113038105892b04854e996105805a8a480000000000000283028b7a01000000000002846d9f080200000000000283189656030000000000018277862e0400000000000185508d200500000000000000"_hex_v_u8, {{573, 6834}}); - TestOptimalLinearization("866faa23008646b71501851f96130282588f1103804d851c0000000003822097600100000003850a8f310200000003856e9201000000038656935f01000003855b8f5f020000018743923a0000000a812b810b010000098403a328020000068712970203000005833e98400400000200"_hex_v_u8, {{-4960, 11011}}); + TestOptimalLinearization("84559211008539851b01825098430285268d1e00010181008e700100028425a22e02000005860a9c1403000005830b924004000005810d87040500000483768808060000038731854007000003862b9066000001010a83799a540100020104850c9a5702010000020482098c0003000002000002826897580400010000010000"_hex_u8, {6, 4, 14, 13, 0, 2, 1, 5, 11, 7, 8, 15, 10, 12, 3, 9}); + TestOptimalLinearization("8657833900865d887e018043894b0287338377038624880100010001851fa82401000000038421990e02000000038723af560300000003866dae0a04000000028265860005000000028031863800000001088353a12c0101000000088630b51a02000000000003866ba1650300000000000300"_hex_u8, {1, 0, 13, 12, 7, 2, 8, 6, 5, 11, 3, 9, 4, 10}); + TestOptimalLinearization("852a9d7d008350920901825193330280691201000181428c25010001823d8d1f020000018355460300000182448c0f040000008608994d05000000843ea14a01000100078511a07001000200058737ad5802000200058569ae3f04010000026e80520401000000058509ac7605000000010400"_hex_u8, {1, 0, 3, 4, 9, 13, 14, 7, 10, 11, 2, 6, 5, 8, 12}); + TestOptimalLinearization("803a88570078825101806a88390282048777038430920a000003811b841f010000038003801c0200000006822092420300000002821a96380400000001820280110500000001806d8834000001000006871aaf2b01000000000003806a8a2a02000000000001864c9e600300000000000100"_hex_u8, {13, 2, 3, 7, 5, 1, 9, 6, 0, 10, 11, 4, 12, 8}); + TestOptimalLinearization("8437801e00845d833f01816b907800000286438821010002867cac720200028202895e030000861db23d00000000068419a47301000000048404966b0200000002812a817c000000058438824b01000004822c980e0200000286168f4c03000002860c8a5b040000008542997a00000000000a8247815101000000000800"_hex_u8, {9, 13, 1, 6, 14, 2, 10, 0, 3, 11, 12, 5, 8, 15, 4, 7}); + TestOptimalLinearization("8556877f0081658a7b01803865028412813e03810e816d048743b56e0581398d070680378048010100000001812e85280100000100000780018226020001000000078370891403000000000100824a994a05000000000000822c835a050000000000000980608376060000000000000100"_hex_u8, {8, 6, 5, 0, 7, 4, 13, 9, 10, 2, 12, 1, 11, 3}); + TestOptimalLinearization("66844f008651aa61018409810902816f814d03823084080000000004843b8144010000000483528d16020000000082758c5403000000008342927f000000000886780c01000000088656802302000000088637b649000004855f8f4001000009815a8c5002000009814b8d240300000900"_hex_u8, {10, 12, 9, 8, 14, 13, 6, 7, 1, 2, 0, 5, 4, 3, 11}); + TestOptimalLinearization("825d842900824a800401864bb0360281598d13038039835f04834a80310585568663068555862e00000000000000078552935e010000000000000785738c5c02000000000000058163864403000000000000058069837e040000000000000480708610050000000000000000"_hex_u8, {6, 3, 10, 11, 2, 9, 8, 12, 1, 7, 5, 4, 0}); + TestOptimalLinearization("83249365008149926b01817a925202874bba1f038631ab2b0484788e55058613992d06857aa671078367883600000100000001844f916e010100010000008179867002000100000100847a90600300000000000007842c902a0500000000000004825e856b0500000000000000068016831206000000000000000200"_hex_u8, {2, 6, 8, 0, 10, 4, 3, 14, 1, 12, 13, 9, 5, 11, 7}); + TestOptimalLinearization("802488410085669221018528aa5b02800a8539038278921601000382338719010103802b8744030102842b8404050002857b886a040102864d9317050100088267920006000001806b813407000100863a5d080000000182529b23000000010000010884259254010000010100000781739540030000000000000600"_hex_u8, {2, 12, 11, 4, 9, 13, 3, 0, 6, 15, 8, 14, 7, 1, 10, 5}); + TestOptimalLinearization("81528b45008715a71201834c8c090102802f85320202866a89320301812985680001068120817301010005837a836a020000000581448a060300000005846e6b0400000001814c9355000100000582758c5a0101000002833b872d02000000000884539c000300000000068459a140000000000b83098f5a010000000300"_hex_u8, {15, 10, 9, 11, 6, 4, 0, 2, 14, 1, 8, 13, 5, 7, 3, 12}); + TestOptimalLinearization("8635a94d00866f9a5901847ea66802821c81640203856694370101018713b00d030001813b8b3603000000811980480400000086108960000100000881068b4301000001028033866202000001008556b22f030000000003835ba028040000000001815789540100000006823d903e01010000058629b01202000000000500"_hex_u8, {6, 3, 2, 12, 1, 13, 4, 5, 14, 15, 0, 8, 9, 11, 10, 7}); + TestOptimalLinearization("81188d5500822c855b01821c3a02863a9117038425930d048207906f057243068235804f07853f8b16000002000108822a8a5601000100010880738e07020001000008850d8c4605010000000681038c2205010000010681628b4a050001000007840a8d440600000002000a8538986a070000000001000000"_hex_u8, {8, 14, 13, 3, 10, 11, 9, 2, 12, 1, 7, 15, 4, 6, 0, 5}); + TestOptimalLinearization("8522934b00812a8b15018610b44e0285789a1f0386509173048233901705840f914906857a924f07831d8e58020000000107860b806502000000010380328724030200000000824b5f0301010000000181518964040000010000000c816e8b24060000000000000b853f45070000000000000400"_hex_u8, {5, 7, 12, 1, 11, 6, 8, 3, 4, 14, 2, 0, 10, 13, 9}); + TestOptimalLinearization("832f8f59008730831a018022822b02801239038275987b048520a0590582448b6506826398500001010007854b971a0100020000088105894c0201000001068737992603000101000387249424040001010003815b82220500000001028706934a0600000100000d8602ae3d0701000000000c844789560801000000000100"_hex_u8, {6, 8, 7, 15, 3, 12, 1, 9, 10, 11, 4, 5, 0, 14, 13, 2}); + TestOptimalLinearization("8458a65900850aac29018201855f02854fab75038461877504821e86330584328d3706861b8d7107844e9d2808847c9250000000030004836d8d3e040000000000098179916402020000010005825b95700400000100000000867dae5e04000000000001000a8162941e05000000000100000682628a4e06000000010000000600"_hex_u8, {14, 6, 13, 4, 10, 12, 5, 0, 2, 8, 7, 15, 3, 11, 9, 1}); + TestOptimalLinearization("8147814100805389410185059d29028045833103850834048073883f05803580330000000106832b9f6c0101000105821c0b020000000000068519a8600300000000000484759a66010000018339a07201000001854ea048020000018730ba160400000086409d3c040000000c00"_hex_u8, {9, 0, 8, 11, 7, 4, 5, 6, 3, 12, 13, 1, 14, 10, 2}); + TestOptimalLinearization("8219866f008118842f01854ba30b0283058a1f038614921b04866a807005840f9b140000000000000584339d1601000000000004834d925402000000000004811d8b3403000000000003844f8552040000000000038217821e0500000000000100"_hex_u8, {11, 2, 0, 9, 8, 5, 3, 6, 1, 4, 7, 10}); + TestOptimalLinearization("8177892100831b9b490181418f05027d803603872c8040048438837805852ea30200000000000006871e956c01000000000005824c9036020000000000018471972203000000000001865d8e28040000000000008566a4100500000000000000"_hex_u8, {5, 9, 6, 1, 4, 3, 0, 11, 7, 8, 2, 10}); + TestOptimalLinearization("8534a80f008374901f018379995e000002807a8c4201000285438d340200028019856403000282178b22040001830b930605000080608b06000000000000048621ad3601000000000001842ba10a02000000000000825494320300000000000000"_hex_u8, {7, 5, 1, 3, 0, 9, 6, 2, 4, 8, 10, 11}); + TestOptimalLinearization("81398a1700805f84750183639f61028032835f0387498f1b048526992b0581688f4e0000000000000480028348010000000000038005821c02000000000003864fad6803000000000003816c9156040000000000038715b5320500000000000000"_hex_u8, {9, 1, 8, 10, 0, 3, 11, 7, 6, 2, 4, 5}); + TestOptimalLinearization("83799c23008671ad4901815c896b02854fab3303810481680000000004803181130100000003845f8743020000000383258862030000000381658f6d0400000002802384590000000000058318876701000000000380758d020000038618951201000366812a02000200"_hex_u8, {12, 6, 1, 13, 5, 0, 3, 2, 10, 7, 4, 8, 9, 11}); + TestOptimalLinearization("8225945300815931018413962f02836a9635038720b46d04842b840f058659974a0000000000000587179118010000000000058710a5540200000000000187169242030000000000018620ac6c04000000000001844182700500000000000000"_hex_u8, {3, 10, 4, 5, 6, 0, 9, 7, 1, 8, 2, 11}); + TestOptimalLinearization("806e801500871ca421018125845d02841a9c3703845da477048528997d058510a820000000000000068745946e01000000000004840f9b1202000000000004822d8e280300000000000484599f0004000000000004807d81050500000000000200"_hex_u8, {1, 7, 11, 2, 8, 10, 0, 6, 4, 5, 3, 9}); + TestOptimalLinearization("84098a0d008000811f01812f831902867a843a038124890f04821e821905870b9e4400000000000004840aa00601000000000002852e97020200000000000284769b18030000000000018042847604000000000001853290160500000000000100"_hex_u8, {4, 11, 3, 0, 1, 7, 5, 8, 9, 2, 6, 10}); + TestOptimalLinearization("834a9b5f00820a89790180598b3f0273815703816e807004805683370580308062068417a42c0000000000000002865098610100000000000000831a93590200000000000000801981000000000a856eb5520100000786409000020000058336903803000005836b9a020400000583599c0c0500000500"_hex_u8, {13, 6, 12, 5, 2, 1, 3, 11, 14, 15, 4, 10, 9, 8, 7, 0}); + TestOptimalLinearization("85268b4c0082748120018068802102807986310381428d770480268659058340994e00000000000004806b8a3e01000000000004811f8c3c02000000000002840a8d6c030000000000018608af5604000000000001822492100500000000000000"_hex_u8, {0, 1, 4, 5, 7, 10, 9, 3, 6, 2, 11, 8}); + TestOptimalLinearization("83718f5300862d9663018700ae190281338d3303825c865104832c916705851b9c64000000000000068419a256010000000000028510a35802000000000001816b861a030000000000018564ad6804000000000001832e85480500000000000100"_hex_u8, {6, 2, 1, 11, 3, 4, 9, 5, 7, 0, 8, 10}); + TestOptimalLinearization("842a980f008356951f01805c82570282308f4303802d8317048415a13705863e51000000000000058530a15201000000000004827c865402000000000004845e93260300000000000281638e68040000000000028121832e0500000000000100"_hex_u8, {5, 9, 0, 2, 6, 11, 8, 3, 7, 10, 4, 1}); + TestOptimalLinearization("855f8024008024816501807c81020284629b030383078631048044895c000002048078100100000000068315856a020000000004800784130300000000028167800c04000000000281758a14010000000885249a1a0100010004852ca63e020000010300"_hex_u8, {6, 1, 12, 5, 11, 3, 4, 10, 0, 8, 9, 7, 2}); + TestOptimalLinearization("855f97230080678a4f018210925d02856113038105892b04854e996105805a8a480000000000000283028b7a01000000000002846d9f080200000000000283189656030000000000018277862e0400000000000185508d200500000000000000"_hex_u8, {3, 0, 10, 7, 2, 1, 4, 8, 6, 5, 11, 9}); + TestOptimalLinearization("866faa23008646b71501851f96130282588f1103804d851c0000000003822097600100000003850a8f310200000003856e9201000000038656935f01000003855b8f5f020000018743923a0000000a812b810b010000098403a328020000068712970203000005833e98400400000200"_hex_u8, {11, 14, 1, 10, 4, 3, 5, 13, 9, 7, 6, 12, 8, 0, 2}); } BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/fuzz/cluster_linearize.cpp b/src/test/fuzz/cluster_linearize.cpp index be23ef3f2e8..b4df22a5372 100644 --- a/src/test/fuzz/cluster_linearize.cpp +++ b/src/test/fuzz/cluster_linearize.cpp @@ -925,7 +925,7 @@ FUZZ_TARGET(clusterlin_sfl) if (rng.randbits(4) == 0) { // Verify that the diagram of GetLinearization() is at least as good as GetDiagram(), // from time to time. - auto lin = sfl.GetLinearization(); + auto lin = sfl.GetLinearization(IndexTxOrder{}); auto lin_diagram = ChunkLinearization(depgraph, lin); auto cmp_lin = CompareChunks(lin_diagram, diagram); assert(cmp_lin >= 0); @@ -1044,7 +1044,7 @@ FUZZ_TARGET(clusterlin_linearize) // Invoke Linearize(). iter_count &= 0x7ffff; - auto [linearization, optimal, cost] = Linearize(depgraph, iter_count, rng_seed, old_linearization, /*is_topological=*/claim_topological_input); + auto [linearization, optimal, cost] = Linearize(depgraph, iter_count, rng_seed, IndexTxOrder{}, old_linearization, /*is_topological=*/claim_topological_input); SanityCheck(depgraph, linearization); auto chunking = ChunkLinearization(depgraph, linearization); @@ -1085,8 +1085,8 @@ FUZZ_TARGET(clusterlin_linearize) // Verify that within every chunk, the transactions are in a valid order. For any pair of // transactions, it should not be possible to swap them; either due to a missing - // dependency, or because the order would be inconsistent with decreasing feerate and - // increasing size. + // dependency, or because the order would be inconsistent with decreasing feerate, + // increasing size, and fallback order (just DepGraphIndex value here). auto chunking_info = ChunkLinearizationInfo(depgraph, linearization); /** The set of all transactions (strictly) before tx1 (see below), or (strictly) before * chunk1 (see even further below). */ @@ -1106,6 +1106,10 @@ FUZZ_TARGET(clusterlin_linearize) // Verify that individual transaction feerate is decreasing (note that >= // tie-breaks by size). assert(depgraph.FeeRate(tx1) >= depgraph.FeeRate(tx2)); + // If feerate and size are equal, compare by DepGraphIndex. + if (depgraph.FeeRate(tx1) == depgraph.FeeRate(tx2)) { + assert(tx1 < tx2); + } } } done.Set(tx1); @@ -1115,7 +1119,8 @@ FUZZ_TARGET(clusterlin_linearize) // Verify that chunks themselves are in a valid order. For any pair of chunks, it should // not be possible to swap them; either due to a missing dependency, or because the order - // would be inconsistent with decreasing chunk feerate and increasing chunk size. + // would be inconsistent with decreasing chunk feerate, increasing chunk size, and order + // of maximum fallback-ordered element (just maximum DepGraphIndex element here). done = {}; // Go over all pairs of chunks. done is the set of transactions seen before chunk_num1. for (unsigned chunk_num1 = 0; chunk_num1 < chunking_info.size(); ++chunk_num1) { @@ -1129,10 +1134,20 @@ FUZZ_TARGET(clusterlin_linearize) // chunk2 could take position chunk_num1. // Verify that chunk feerate is decreasing (note that >= tie-breaks by size). assert(chunk1.feerate >= chunk2.feerate); + // If feerate and size are equal, compare by maximum DepGraphIndex element. + if (chunk1.feerate == chunk2.feerate) { + assert(chunk1.transactions.Last() < chunk2.transactions.Last()); + } } } done |= chunk1.transactions; } + + // Redo from scratch with a different rng_seed. The resulting linearization should be + // deterministic, if both are optimal. + auto [linearization2, optimal2, cost2] = Linearize(depgraph, MaxOptimalLinearizationIters(depgraph.TxCount()) + 1, rng_seed ^ 0x1337, IndexTxOrder{}); + assert(optimal2); + assert(linearization2 == linearization); } } @@ -1221,7 +1236,7 @@ FUZZ_TARGET(clusterlin_postlinearize_tree) // Try to find an even better linearization directly. This must not change the diagram for the // same reason. - auto [opt_linearization, _optimal, _cost] = Linearize(depgraph_tree, 100000, rng_seed, post_linearization); + auto [opt_linearization, _optimal, _cost] = Linearize(depgraph_tree, 100000, rng_seed, IndexTxOrder{}, post_linearization); auto opt_chunking = ChunkLinearization(depgraph_tree, opt_linearization); auto cmp_opt = CompareChunks(opt_chunking, post_chunking); assert(cmp_opt == 0); diff --git a/src/test/fuzz/txgraph.cpp b/src/test/fuzz/txgraph.cpp index 49945e65b15..214ed9e2e30 100644 --- a/src/test/fuzz/txgraph.cpp +++ b/src/test/fuzz/txgraph.cpp @@ -1065,7 +1065,8 @@ FUZZ_TARGET(txgraph) // that calling Linearize on it does not improve it further. if (sims[0].real_is_optimal) { auto real_diagram = ChunkLinearization(sims[0].graph, vec1); - auto [sim_lin, _optimal, _cost] = Linearize(sims[0].graph, 300000, rng.rand64(), vec1); + auto [sim_lin, sim_optimal, _cost] = Linearize(sims[0].graph, 300000, rng.rand64(), IndexTxOrder{}, vec1); + PostLinearize(sims[0].graph, sim_lin); auto sim_diagram = ChunkLinearization(sims[0].graph, sim_lin); auto cmp = CompareChunks(real_diagram, sim_diagram); assert(cmp == 0); @@ -1094,11 +1095,27 @@ FUZZ_TARGET(txgraph) auto comp_key = component.First(); auto& comp_prefix_size = comp_prefix_sizes[comp_key]; comp_prefix_size += chunk.feerate.size; - // Verify consistency: within each component (= cluster in txgraph), the - // equal-feerate chunk prefix size must be monotonically increasing. + // Verify consistency: within each group of equal-feerate chunks, the equal-feerate + // chunk prefix size must be monotonically increasing. assert(comp_prefix_size >= max_chunk_prefix_size); max_chunk_prefix_size = comp_prefix_size; } + + // Verify that within each cluster, the internal ordering matches that of the + // simulation if that is optimal too, since per-cluster optimal orderings are + // deterministic. Note that both have been PostLinearize()'ed. + if (sim_optimal) { + for (const auto& component : sims[0].GetComponents()) { + std::vector sim_chunk_lin, real_chunk_lin; + for (auto i : sim_lin) { + if (component[i]) sim_chunk_lin.push_back(i); + } + for (auto i : vec1) { + if (component[i]) real_chunk_lin.push_back(i); + } + assert(sim_chunk_lin == real_chunk_lin); + } + } } // For every transaction in the total ordering, find a random one before it and after it, diff --git a/src/txgraph.cpp b/src/txgraph.cpp index 60c8b1facb8..492356a899d 100644 --- a/src/txgraph.cpp +++ b/src/txgraph.cpp @@ -2132,9 +2132,11 @@ std::pair GenericClusterImpl::Relinearize(TxGraphImpl& graph, in if (IsOptimal()) return {0, false}; // Invoke the actual linearization algorithm (passing in the existing one). uint64_t rng_seed = graph.m_rng.rand64(); - auto [linearization, optimal, cost] = Linearize(m_depgraph, max_iters, rng_seed, m_linearization, /*is_topological=*/IsTopological()); - // Postlinearize to undo some of the non-determinism caused by randomizing the linearization. - // This also guarantees that all chunks are connected (even when non-optimal). + auto [linearization, optimal, cost] = Linearize(m_depgraph, max_iters, rng_seed, IndexTxOrder{}, m_linearization, /*is_topological=*/IsTopological()); + // Postlinearize to improve the linearization (if optimal, only the sub-chunk order), and + // reduce the amount of information the IndexTxOrder-based fallback order leaks about + // DepGraphIndexes in the cluster. This also guarantees that all chunks are connected (even + // when non-optimal). PostLinearize(m_depgraph, linearization); // Update the linearization. m_linearization = std::move(linearization); From 941c432a4637efd4e5040259f47f2bfed073af7c Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Wed, 7 Jan 2026 17:17:16 -0500 Subject: [PATCH 07/10] txgraph test: subclass TxGraph::Ref like mempool does (preparation) This is a small change to the txgraph fuzz test to make it used objects derived from TxGraph::Ref (SimTxObject) rather than TxGraph::Ref directly. This matches how the mempool uses CTxMemPoolEntry, which derives from TxGraph::Ref. This is preparation for a future commit which will introduce simulated txids to the transactions in this fuzz test, to be used as fallback order. --- src/test/fuzz/txgraph.cpp | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/src/test/fuzz/txgraph.cpp b/src/test/fuzz/txgraph.cpp index 214ed9e2e30..51546f612ec 100644 --- a/src/test/fuzz/txgraph.cpp +++ b/src/test/fuzz/txgraph.cpp @@ -23,6 +23,10 @@ using namespace cluster_linearize; namespace { +struct SimTxObject : public TxGraph::Ref +{ +}; + /** Data type representing a naive simulated TxGraph, keeping all transactions (even from * disconnected components) in a single DepGraph. Unlike the real TxGraph, this only models * a single graph, and multiple instances are used to simulate main/staging. */ @@ -42,14 +46,14 @@ struct SimTxGraph /** The dependency graph (for all transactions in the simulation, regardless of * connectivity/clustering). */ DepGraph graph; - /** For each position in graph, which TxGraph::Ref it corresponds with (if any). Use shared_ptr + /** For each position in graph, which SimTxObject it corresponds with (if any). Use shared_ptr * so that a SimTxGraph can be copied to create a staging one, while sharing Refs with * the main graph. */ - std::array, MAX_TRANSACTIONS> simmap; + std::array, MAX_TRANSACTIONS> simmap; /** For each TxGraph::Ref in graph, the position it corresponds with. */ std::map simrevmap; - /** The set of TxGraph::Ref entries that have been removed, but not yet destroyed. */ - std::vector> removed; + /** The set of SimTxObject entries that have been removed, but not yet destroyed. */ + std::vector> removed; /** Whether the graph is oversized (true = yes, false = no, std::nullopt = unknown). */ std::optional oversized; /** The configured maximum number of transactions per cluster. */ @@ -129,8 +133,8 @@ struct SimTxGraph return MISSING; } - /** Given a position in this simulated graph, get the corresponding TxGraph::Ref. */ - TxGraph::Ref* GetRef(Pos pos) + /** Given a position in this simulated graph, get the corresponding SimTxObject. */ + SimTxObject* GetRef(Pos pos) { assert(graph.Positions()[pos]); assert(simmap[pos]); @@ -145,7 +149,7 @@ struct SimTxGraph real_is_optimal = false; MakeModified(simpos); assert(graph.Positions()[simpos]); - simmap[simpos] = std::make_shared(); + simmap[simpos] = std::make_shared(); txgraph.AddTransaction(*simmap[simpos], feerate); auto ptr = simmap[simpos].get(); simrevmap[ptr] = simpos; @@ -309,8 +313,8 @@ FUZZ_TARGET(txgraph) * specialized test cases that are hard to perform more generically. */ InsecureRandomContext rng(provider.ConsumeIntegral()); - /** Variable used whenever an empty TxGraph::Ref is needed. */ - TxGraph::Ref empty_ref; + /** Variable used whenever an empty SimTxObject is needed. */ + SimTxObject empty_ref; /** The maximum number of transactions per (non-oversized) cluster we will use in this * simulation. */ @@ -344,9 +348,9 @@ FUZZ_TARGET(txgraph) /** Currently active block builders. */ std::vector block_builders; - /** Function to pick any Ref (for either sim in sims: from sim.simmap or sim.removed, or the - * empty Ref). */ - auto pick_fn = [&]() noexcept -> TxGraph::Ref* { + /** Function to pick any SimTxObject (for either sim in sims: from sim.simmap or sim.removed, or the + * empty one). */ + auto pick_fn = [&]() noexcept -> SimTxObject* { size_t tx_count[2] = {sims[0].GetTransactionCount(), 0}; /** The number of possible choices. */ size_t choices = tx_count[0] + sims[0].removed.size() + 1; From fba004a3df02d8d5d47f1ad0bb1ccbfde01bb2af Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Thu, 8 Jan 2026 15:17:28 -0500 Subject: [PATCH 08/10] txgraph: pass fallback_order to TxGraph (preparation) This adds an std::function argument to the MakeTxGraph function, which can be used by the caller (e.g., mempool code) to provide a fallback order to TxGraph. This is just preparation; TxGraph does not yet use this fallback order for anything. --- src/bench/txgraph.cpp | 7 ++++- src/primitives/transaction_identifier.h | 3 +- src/test/fuzz/txgraph.cpp | 40 +++++++++++++++++++++---- src/test/txgraph_tests.cpp | 23 +++++++++----- src/txgraph.cpp | 20 ++++++++++--- src/txgraph.h | 20 ++++++++++--- src/txmempool.cpp | 10 ++++++- 7 files changed, 100 insertions(+), 23 deletions(-) diff --git a/src/bench/txgraph.cpp b/src/bench/txgraph.cpp index 7257a043777..00074db658f 100644 --- a/src/bench/txgraph.cpp +++ b/src/bench/txgraph.cpp @@ -12,6 +12,11 @@ namespace { +std::strong_ordering PointerComparator(const TxGraph::Ref& a, const TxGraph::Ref& b) noexcept +{ + return (&a) <=> (&b); +} + void BenchTxGraphTrim(benchmark::Bench& bench) { // The from-block transactions consist of 1000 fully linear clusters, each with 64 @@ -60,7 +65,7 @@ void BenchTxGraphTrim(benchmark::Bench& bench) std::vector top_components; InsecureRandomContext rng(11); - auto graph = MakeTxGraph(MAX_CLUSTER_COUNT, MAX_CLUSTER_SIZE, NUM_ACCEPTABLE_ITERS); + auto graph = MakeTxGraph(MAX_CLUSTER_COUNT, MAX_CLUSTER_SIZE, NUM_ACCEPTABLE_ITERS, PointerComparator); // Construct the top chains. for (int chain = 0; chain < NUM_TOP_CHAINS; ++chain) { diff --git a/src/primitives/transaction_identifier.h b/src/primitives/transaction_identifier.h index 9b518d7d795..a1109591277 100644 --- a/src/primitives/transaction_identifier.h +++ b/src/primitives/transaction_identifier.h @@ -9,6 +9,7 @@ #include #include +#include #include #include #include @@ -42,7 +43,7 @@ public: template bool operator==(const Other& other) const { return Compare(other) == 0; } template - bool operator<(const Other& other) const { return Compare(other) < 0; } + std::strong_ordering operator<=>(const Other& other) const { return Compare(other) <=> 0; } const uint256& ToUint256() const LIFETIMEBOUND { return m_wrapped; } static transaction_identifier FromUint256(const uint256& id) { return {id}; } diff --git a/src/test/fuzz/txgraph.cpp b/src/test/fuzz/txgraph.cpp index 51546f612ec..5352e2c1e30 100644 --- a/src/test/fuzz/txgraph.cpp +++ b/src/test/fuzz/txgraph.cpp @@ -25,6 +25,10 @@ namespace { struct SimTxObject : public TxGraph::Ref { + // Use random uint64_t as txids for this simulation (0 = empty object). + const uint64_t m_txid{0}; + SimTxObject() noexcept = default; + explicit SimTxObject(uint64_t txid) noexcept : m_txid(txid) {} }; /** Data type representing a naive simulated TxGraph, keeping all transactions (even from @@ -142,14 +146,14 @@ struct SimTxGraph } /** Add a new transaction to the simulation and the specified real graph. */ - void AddTransaction(TxGraph& txgraph, const FeePerWeight& feerate) + void AddTransaction(TxGraph& txgraph, const FeePerWeight& feerate, uint64_t txid) { assert(graph.TxCount() < MAX_TRANSACTIONS); auto simpos = graph.AddTransaction(feerate); real_is_optimal = false; MakeModified(simpos); assert(graph.Positions()[simpos]); - simmap[simpos] = std::make_shared(); + simmap[simpos] = std::make_shared(txid); txgraph.AddTransaction(*simmap[simpos], feerate); auto ptr = simmap[simpos].get(); simrevmap[ptr] = simpos; @@ -324,8 +328,23 @@ FUZZ_TARGET(txgraph) /** The number of iterations to consider a cluster acceptably linearized. */ auto acceptable_iters = provider.ConsumeIntegralInRange(0, 10000); + /** The set of uint64_t "txid"s that have been assigned before. */ + std::set assigned_txids; + // Construct a real graph, and a vector of simulated graphs (main, and possibly staging). - auto real = MakeTxGraph(max_cluster_count, max_cluster_size, acceptable_iters); + auto fallback_order = [&](const TxGraph::Ref& a, const TxGraph::Ref& b) noexcept { + uint64_t txid_a = static_cast(a).m_txid; + uint64_t txid_b = static_cast(b).m_txid; + assert(assigned_txids.contains(txid_a)); + assert(assigned_txids.contains(txid_b)); + return txid_a <=> txid_b; + }; + auto real = MakeTxGraph( + /*max_cluster_count=*/max_cluster_count, + /*max_cluster_size=*/max_cluster_size, + /*acceptable_iters=*/acceptable_iters, + /*fallback_order=*/fallback_order); + std::vector sims; sims.reserve(2); sims.emplace_back(max_cluster_count, max_cluster_size); @@ -460,8 +479,14 @@ FUZZ_TARGET(txgraph) size = provider.ConsumeIntegralInRange(1, 0xff); } FeePerWeight feerate{fee, size}; + // Pick a novel txid (and not 0, which is reserved for empty_ref). + uint64_t txid; + do { + txid = rng.rand64(); + } while (txid == 0 || assigned_txids.contains(txid)); + assigned_txids.insert(txid); // Create the transaction in the simulation and the real graph. - top_sim.AddTransaction(*real, feerate); + top_sim.AddTransaction(*real, feerate, txid); break; } else if ((block_builders.empty() || sims.size() > 1) && top_sim.GetTransactionCount() + top_sim.removed.size() > 1 && command-- == 0) { // AddDependency. @@ -1069,7 +1094,12 @@ FUZZ_TARGET(txgraph) // that calling Linearize on it does not improve it further. if (sims[0].real_is_optimal) { auto real_diagram = ChunkLinearization(sims[0].graph, vec1); - auto [sim_lin, sim_optimal, _cost] = Linearize(sims[0].graph, 300000, rng.rand64(), IndexTxOrder{}, vec1); + auto fallback_order_sim = [&](DepGraphIndex a, DepGraphIndex b) noexcept { + auto txid_a = sims[0].GetRef(a)->m_txid; + auto txid_b = sims[0].GetRef(b)->m_txid; + return txid_a <=> txid_b; + }; + auto [sim_lin, sim_optimal, _cost] = Linearize(sims[0].graph, 300000, rng.rand64(), fallback_order_sim, vec1); PostLinearize(sims[0].graph, sim_lin); auto sim_diagram = ChunkLinearization(sims[0].graph, sim_lin); auto cmp = CompareChunks(real_diagram, sim_diagram); diff --git a/src/test/txgraph_tests.cpp b/src/test/txgraph_tests.cpp index 31fefd9ce18..f069e5bdc75 100644 --- a/src/test/txgraph_tests.cpp +++ b/src/test/txgraph_tests.cpp @@ -13,9 +13,18 @@ BOOST_AUTO_TEST_SUITE(txgraph_tests) +namespace { + /** The number used as acceptable_iters argument in these tests. High enough that everything * should be optimal, always. */ -static constexpr uint64_t NUM_ACCEPTABLE_ITERS = 100'000'000; +constexpr uint64_t NUM_ACCEPTABLE_ITERS = 100'000'000; + +std::strong_ordering PointerComparator(const TxGraph::Ref& a, const TxGraph::Ref& b) noexcept +{ + return (&a) <=> (&b); +} + +} // namespace BOOST_AUTO_TEST_CASE(txgraph_trim_zigzag) { @@ -39,7 +48,7 @@ BOOST_AUTO_TEST_CASE(txgraph_trim_zigzag) static constexpr int32_t MAX_CLUSTER_SIZE = 100'000 * 100; // Create a new graph for the test. - auto graph = MakeTxGraph(MAX_CLUSTER_COUNT, MAX_CLUSTER_SIZE, NUM_ACCEPTABLE_ITERS); + auto graph = MakeTxGraph(MAX_CLUSTER_COUNT, MAX_CLUSTER_SIZE, NUM_ACCEPTABLE_ITERS, PointerComparator); // Add all transactions and store their Refs. std::vector refs; @@ -102,7 +111,7 @@ BOOST_AUTO_TEST_CASE(txgraph_trim_flower) /** Set a very large cluster size limit so that only the count limit is triggered. */ static constexpr int32_t MAX_CLUSTER_SIZE = 100'000 * 100; - auto graph = MakeTxGraph(MAX_CLUSTER_COUNT, MAX_CLUSTER_SIZE, NUM_ACCEPTABLE_ITERS); + auto graph = MakeTxGraph(MAX_CLUSTER_COUNT, MAX_CLUSTER_SIZE, NUM_ACCEPTABLE_ITERS, PointerComparator); // Add all transactions and store their Refs. std::vector refs; @@ -188,7 +197,7 @@ BOOST_AUTO_TEST_CASE(txgraph_trim_huge) std::vector top_components; FastRandomContext rng; - auto graph = MakeTxGraph(MAX_CLUSTER_COUNT, MAX_CLUSTER_SIZE, NUM_ACCEPTABLE_ITERS); + auto graph = MakeTxGraph(MAX_CLUSTER_COUNT, MAX_CLUSTER_SIZE, NUM_ACCEPTABLE_ITERS, PointerComparator); // Construct the top chains. for (int chain = 0; chain < NUM_TOP_CHAINS; ++chain) { @@ -261,7 +270,7 @@ BOOST_AUTO_TEST_CASE(txgraph_trim_big_singletons) static constexpr int NUM_TOTAL_TX = 100; // Create a new graph for the test. - auto graph = MakeTxGraph(MAX_CLUSTER_COUNT, MAX_CLUSTER_SIZE, NUM_ACCEPTABLE_ITERS); + auto graph = MakeTxGraph(MAX_CLUSTER_COUNT, MAX_CLUSTER_SIZE, NUM_ACCEPTABLE_ITERS, PointerComparator); // Add all transactions and store their Refs. std::vector refs; @@ -295,7 +304,7 @@ BOOST_AUTO_TEST_CASE(txgraph_trim_big_singletons) BOOST_AUTO_TEST_CASE(txgraph_chunk_chain) { // Create a new graph for the test. - auto graph = MakeTxGraph(50, 1000, NUM_ACCEPTABLE_ITERS); + auto graph = MakeTxGraph(50, 1000, NUM_ACCEPTABLE_ITERS, PointerComparator); auto block_builder_checker = [&graph](std::vector> expected_chunks) { std::vector> chunks; @@ -374,7 +383,7 @@ BOOST_AUTO_TEST_CASE(txgraph_staging) /* Create a new graph for the test. * The parameters are max_cluster_count, max_cluster_size, acceptable_iters */ - auto graph = MakeTxGraph(10, 1000, NUM_ACCEPTABLE_ITERS); + auto graph = MakeTxGraph(10, 1000, NUM_ACCEPTABLE_ITERS, PointerComparator); std::vector refs; refs.reserve(2); diff --git a/src/txgraph.cpp b/src/txgraph.cpp index 492356a899d..2c024c969a7 100644 --- a/src/txgraph.cpp +++ b/src/txgraph.cpp @@ -403,6 +403,8 @@ private: /** The number of linearization improvement steps needed per cluster to be considered * acceptable. */ const uint64_t m_acceptable_iters; + /** Fallback ordering for transactions. */ + const std::function m_fallback_order; /** Information about one group of Clusters to be merged. */ struct GroupEntry @@ -621,11 +623,17 @@ private: std::vector m_unlinked; public: - /** Construct a new TxGraphImpl with the specified limits. */ - explicit TxGraphImpl(DepGraphIndex max_cluster_count, uint64_t max_cluster_size, uint64_t acceptable_iters) noexcept : + /** Construct a new TxGraphImpl with the specified limits and fallback order. */ + explicit TxGraphImpl( + DepGraphIndex max_cluster_count, + uint64_t max_cluster_size, + uint64_t acceptable_iters, + const std::function& fallback_order + ) noexcept : m_max_cluster_count(max_cluster_count), m_max_cluster_size(max_cluster_size), m_acceptable_iters(acceptable_iters), + m_fallback_order(fallback_order), m_main_chunkindex(ChunkOrder(this)) { Assume(max_cluster_count >= 1); @@ -3523,7 +3531,11 @@ TxGraph::Ref::Ref(Ref&& other) noexcept std::swap(m_index, other.m_index); } -std::unique_ptr MakeTxGraph(unsigned max_cluster_count, uint64_t max_cluster_size, uint64_t acceptable_iters) noexcept +std::unique_ptr MakeTxGraph( + unsigned max_cluster_count, + uint64_t max_cluster_size, + uint64_t acceptable_iters, + const std::function& fallback_order) noexcept { - return std::make_unique(max_cluster_count, max_cluster_size, acceptable_iters); + return std::make_unique(max_cluster_count, max_cluster_size, acceptable_iters, fallback_order); } diff --git a/src/txgraph.h b/src/txgraph.h index 385db0147cc..8c7a91744fd 100644 --- a/src/txgraph.h +++ b/src/txgraph.h @@ -4,6 +4,7 @@ #include #include +#include #include #include #include @@ -253,9 +254,20 @@ public: }; /** Construct a new TxGraph with the specified limit on the number of transactions within a cluster, - * and on the sum of transaction sizes within a cluster. max_cluster_count cannot exceed - * MAX_CLUSTER_COUNT_LIMIT. acceptable_iters controls how many linearization optimization - * steps will be performed per cluster before they are considered to be of acceptable quality. */ -std::unique_ptr MakeTxGraph(unsigned max_cluster_count, uint64_t max_cluster_size, uint64_t acceptable_iters) noexcept; + * and on the sum of transaction sizes within a cluster. + * + * - max_cluster_count cannot exceed MAX_CLUSTER_COUNT_LIMIT. + * - acceptable_iters controls how many linearization optimization steps will be performed per + * cluster before they are considered to be of acceptable quality. + * - fallback_order determines how to break tie-breaks between transactions: + * fallback_order(a, b) < 0 means a is "better" than b, and will (in case of ties) be placed + * first. This ordering must be stable over the transactions' lifetimes. + */ +std::unique_ptr MakeTxGraph( + unsigned max_cluster_count, + uint64_t max_cluster_size, + uint64_t acceptable_iters, + const std::function& fallback_order +) noexcept; #endif // BITCOIN_TXGRAPH_H diff --git a/src/txmempool.cpp b/src/txmempool.cpp index 58262e7f2f9..b8be3e080e7 100644 --- a/src/txmempool.cpp +++ b/src/txmempool.cpp @@ -176,7 +176,15 @@ static CTxMemPool::Options&& Flatten(CTxMemPool::Options&& opts, bilingual_str& CTxMemPool::CTxMemPool(Options opts, bilingual_str& error) : m_opts{Flatten(std::move(opts), error)} { - m_txgraph = MakeTxGraph(m_opts.limits.cluster_count, m_opts.limits.cluster_size_vbytes * WITNESS_SCALE_FACTOR, ACCEPTABLE_ITERS); + m_txgraph = MakeTxGraph( + /*max_cluster_count=*/m_opts.limits.cluster_count, + /*max_cluster_size=*/m_opts.limits.cluster_size_vbytes * WITNESS_SCALE_FACTOR, + /*acceptable_iters=*/ACCEPTABLE_ITERS, + /*fallback_order=*/[&](const TxGraph::Ref& a, const TxGraph::Ref& b) noexcept { + const Txid& txid_a = static_cast(a).GetTx().GetHash(); + const Txid& txid_b = static_cast(b).GetTx().GetHash(); + return txid_a <=> txid_b; + }); } bool CTxMemPool::isSpent(const COutPoint& outpoint) const From 0a3351947e736c646a6dfffef24b83d003c569e7 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Sat, 10 Jan 2026 23:28:00 -0500 Subject: [PATCH 09/10] txgraph: use fallback order when linearizing (feature) Add glue to make TxGraph use the fallback order provided to it, in the fallback comparator it provides to the cluster linearization code. The order of chunks within a cluster becomes: 1. Topology (chunks after their dependencies) 2. Feerate (high to low) 3. Weight (small to large) 4. Max-txid (chunk with lowest maximum-txid first) The order of transactions within a chunk becomes: 1. Topology (parents before children) 2. Individual transaction feerate (high to low) 3. Weight (small to large) 4. Txid (low to high txid) This makes optimal cluster linearization, both the order of chunks within a chunk, and the order of transactions within those chunks, completely deterministic. --- src/txgraph.cpp | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/txgraph.cpp b/src/txgraph.cpp index 2c024c969a7..176ef613c71 100644 --- a/src/txgraph.cpp +++ b/src/txgraph.cpp @@ -2140,11 +2140,14 @@ std::pair GenericClusterImpl::Relinearize(TxGraphImpl& graph, in if (IsOptimal()) return {0, false}; // Invoke the actual linearization algorithm (passing in the existing one). uint64_t rng_seed = graph.m_rng.rand64(); - auto [linearization, optimal, cost] = Linearize(m_depgraph, max_iters, rng_seed, IndexTxOrder{}, m_linearization, /*is_topological=*/IsTopological()); - // Postlinearize to improve the linearization (if optimal, only the sub-chunk order), and - // reduce the amount of information the IndexTxOrder-based fallback order leaks about - // DepGraphIndexes in the cluster. This also guarantees that all chunks are connected (even - // when non-optimal). + const auto fallback_order = [&](DepGraphIndex a, DepGraphIndex b) noexcept { + const auto ref_a = graph.m_entries[m_mapping[a]].m_ref; + const auto ref_b = graph.m_entries[m_mapping[b]].m_ref; + return graph.m_fallback_order(*ref_a, *ref_b); + }; + auto [linearization, optimal, cost] = Linearize(m_depgraph, max_iters, rng_seed, fallback_order, m_linearization, /*is_topological=*/IsTopological()); + // Postlinearize to improve the linearization (if optimal, only the sub-chunk order). + // This also guarantees that all chunks are connected (even when non-optimal). PostLinearize(m_depgraph, linearization); // Update the linearization. m_linearization = std::move(linearization); From 6f113cb1847c6890f1fbd052ff7eb8ea41ccafc5 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Sat, 10 Jan 2026 23:28:14 -0500 Subject: [PATCH 10/10] txgraph: use fallback order to sort chunks (feature) This makes TxGraph also use the fallback order to decide the order of chunks from distinct clusters. The order of chunks across clusters becomes: 1. Feerate (high to low) 2. Equal-feerate-chunk-prefix (small to large) 3. Max-txid (chunk with lowest maximum-txid first) This makes the full TxGraph ordering fully deterministic as long as all clusters in it are optimally linearized. --- src/test/fuzz/txgraph.cpp | 67 ++++++++++++++++++++++++++--- src/txgraph.cpp | 40 ++++++++++++++--- test/functional/mempool_packages.py | 6 +-- 3 files changed, 97 insertions(+), 16 deletions(-) diff --git a/src/test/fuzz/txgraph.cpp b/src/test/fuzz/txgraph.cpp index 5352e2c1e30..59c65bde8b7 100644 --- a/src/test/fuzz/txgraph.cpp +++ b/src/test/fuzz/txgraph.cpp @@ -1114,13 +1114,13 @@ FUZZ_TARGET(txgraph) std::map comp_prefix_sizes; /** Current chunk feerate. */ FeeFrac last_chunk_feerate; - /** Largest seen equal-feerate chunk prefix size. */ - int32_t max_chunk_prefix_size{0}; + /** Largest seen (equal-feerate chunk prefix size, max txid). */ + std::pair max_chunk_tiebreak{0, 0}; for (const auto& chunk : real_chunking) { // If this is the first chunk with a strictly lower feerate, reset. if (chunk.feerate << last_chunk_feerate) { comp_prefix_sizes.clear(); - max_chunk_prefix_size = 0; + max_chunk_tiebreak = {0, 0}; } last_chunk_feerate = chunk.feerate; // Find which sim component this chunk belongs to. @@ -1129,10 +1129,17 @@ FUZZ_TARGET(txgraph) auto comp_key = component.First(); auto& comp_prefix_size = comp_prefix_sizes[comp_key]; comp_prefix_size += chunk.feerate.size; - // Verify consistency: within each group of equal-feerate chunks, the equal-feerate - // chunk prefix size must be monotonically increasing. - assert(comp_prefix_size >= max_chunk_prefix_size); - max_chunk_prefix_size = comp_prefix_size; + // Determine the chunk's max txid. + uint64_t chunk_max_txid{0}; + for (auto tx : chunk.transactions) { + auto txid = sims[0].GetRef(tx)->m_txid; + chunk_max_txid = std::max(txid, chunk_max_txid); + } + // Verify consistency: within each group of equal-feerate chunks, the + // (equal-feerate chunk prefix size, max txid) must be increasing. + std::pair chunk_tiebreak{comp_prefix_size, chunk_max_txid}; + assert(chunk_tiebreak > max_chunk_tiebreak); + max_chunk_tiebreak = chunk_tiebreak; } // Verify that within each cluster, the internal ordering matches that of the @@ -1150,6 +1157,52 @@ FUZZ_TARGET(txgraph) assert(sim_chunk_lin == real_chunk_lin); } } + + // Verify that a fresh TxGraph, with the same transactions and txids, but constructed + // in a different order, and with a different RNG state, recreates the exact same + // ordering, showing that for optimal graphs, the full mempool ordering is + // deterministic. + auto real_redo = MakeTxGraph( + /*max_cluster_count=*/max_cluster_count, + /*max_cluster_size=*/max_cluster_size, + /*acceptable_iters=*/acceptable_iters, + /*fallback_order=*/fallback_order); + /** Vector (indexed by SimTxGraph::Pos) of TxObjects in real_redo). */ + std::vector> txobjects_redo; + txobjects_redo.resize(sims[0].graph.PositionRange()); + // Recreate the graph's transactions with same feerate and txid. + std::vector positions; + for (auto i : sims[0].graph.Positions()) positions.push_back(i); + std::shuffle(positions.begin(), positions.end(), rng); + for (auto i : positions) { + txobjects_redo[i].emplace(sims[0].GetRef(i)->m_txid); + real_redo->AddTransaction(*txobjects_redo[i], FeePerWeight::FromFeeFrac(sims[0].graph.FeeRate(i))); + } + // Recreate the graph's dependencies. + std::vector> deps; + for (auto i : sims[0].graph.Positions()) { + for (auto j : sims[0].graph.GetReducedParents(i)) { + deps.emplace_back(j, i); + } + } + std::shuffle(deps.begin(), deps.end(), rng); + for (auto [parent, child] : deps) { + real_redo->AddDependency(*txobjects_redo[parent], *txobjects_redo[child]); + } + // Do work to reach optimality. + if (real_redo->DoWork(300000)) { + // Start from a random permutation. + auto vec_redo = vec1; + std::shuffle(vec_redo.begin(), vec_redo.end(), rng); + if (vec_redo == vec1) std::next_permutation(vec_redo.begin(), vec_redo.end()); + // Sort it according to the main graph order in real_redo. + auto cmp_redo = [&](SimTxGraph::Pos a, SimTxGraph::Pos b) noexcept { + return real_redo->CompareMainOrder(*txobjects_redo[a], *txobjects_redo[b]) < 0; + }; + std::sort(vec_redo.begin(), vec_redo.end(), cmp_redo); + // Compare with the ordering we got from real. + assert(vec1 == vec_redo); + } } // For every transaction in the total ordering, find a random one before it and after it, diff --git a/src/txgraph.cpp b/src/txgraph.cpp index 176ef613c71..a9d502b444c 100644 --- a/src/txgraph.cpp +++ b/src/txgraph.cpp @@ -492,6 +492,7 @@ private: /** Compare two entries (which must both exist within the main graph). */ std::strong_ordering CompareMainTransactions(GraphIndex a, GraphIndex b) const noexcept { + if (a == b) return std::strong_ordering::equal; Assume(a < m_entries.size() && b < m_entries.size()); const auto& entry_a = m_entries[a]; const auto& entry_b = m_entries[b]; @@ -506,12 +507,17 @@ private: if (entry_a.m_main_equal_feerate_chunk_prefix_size != entry_b.m_main_equal_feerate_chunk_prefix_size) { return entry_a.m_main_equal_feerate_chunk_prefix_size <=> entry_b.m_main_equal_feerate_chunk_prefix_size; } - // Compare Cluster m_sequence as tie-break for equal chunk feerates in distinct clusters, - // when the equal-feerate-prefix size is also the same. + // Compare by maximum m_fallback_order element to order equal-feerate chunks in distinct + // clusters, when the equal-feerate-prefix size is also the same. const auto& locator_a = entry_a.m_locator[0]; const auto& locator_b = entry_b.m_locator[0]; Assume(locator_a.IsPresent() && locator_b.IsPresent()); if (locator_a.cluster != locator_b.cluster) { + auto fallback_cmp = m_fallback_order(*m_entries[entry_a.m_main_max_chunk_fallback].m_ref, + *m_entries[entry_b.m_main_max_chunk_fallback].m_ref); + if (fallback_cmp != 0) return fallback_cmp; + // This shouldn't be reachable as m_fallback_order defines a strong ordering. + Assume(false); return CompareClusters(locator_a.cluster, locator_b.cluster); } // Within a single chunk, sort by position within cluster linearization. @@ -614,6 +620,9 @@ private: int32_t m_main_equal_feerate_chunk_prefix_size; /** The position this transaction has in the main linearization (if present). */ LinearizationIndex m_main_lin_index; + /** Of all transactions within this transaction's chunk in main (if present there), the + * maximal one according to m_fallback_order. */ + GraphIndex m_main_max_chunk_fallback = GraphIndex(-1); }; /** The set of all transactions (in all levels combined). GraphIndex values index into this. */ @@ -884,6 +893,9 @@ void TxGraphImpl::ClearChunkData(Entry& entry) noexcept void TxGraphImpl::CreateChunkData(GraphIndex idx, LinearizationIndex chunk_count) noexcept { auto& entry = m_entries[idx]; + // Make sure to not create chunk data for unlinked entries, which would make invoking + // m_fallback_order on them impossible. + Assume(entry.m_ref != nullptr); if (!m_main_chunkindex_discarded.empty()) { // Reuse an discarded node handle. auto& node = m_main_chunkindex_discarded.back().value(); @@ -1096,6 +1108,17 @@ void GenericClusterImpl::Updated(TxGraphImpl& graph, int level, bool rename) noe // ratio remains the same; it's just accounting for the size of the added chunk. equal_feerate_chunk_feerate += chunk.feerate; } + // Determine the m_fallback_order maximum transaction in the chunk. + auto it = chunk.transactions.begin(); + GraphIndex max_element = m_mapping[*it]; + ++it; + while (it != chunk.transactions.end()) { + GraphIndex this_element = m_mapping[*it]; + if (graph.m_fallback_order(*graph.m_entries[this_element].m_ref, *graph.m_entries[max_element].m_ref) > 0) { + max_element = this_element; + } + ++it; + } // Iterate over the transactions in the linearization, which must match those in chunk. while (true) { DepGraphIndex idx = m_linearization[lin_idx]; @@ -1104,6 +1127,7 @@ void GenericClusterImpl::Updated(TxGraphImpl& graph, int level, bool rename) noe entry.m_main_lin_index = lin_idx++; entry.m_main_chunk_feerate = FeePerWeight::FromFeeFrac(chunk.feerate); entry.m_main_equal_feerate_chunk_prefix_size = equal_feerate_chunk_feerate.size; + entry.m_main_max_chunk_fallback = max_element; Assume(chunk.transactions[idx]); chunk.transactions.Reset(idx); if (chunk.transactions.None()) { @@ -1138,6 +1162,7 @@ void SingletonClusterImpl::Updated(TxGraphImpl& graph, int level, bool rename) n entry.m_main_lin_index = 0; entry.m_main_chunk_feerate = m_feerate; entry.m_main_equal_feerate_chunk_prefix_size = m_feerate.size; + entry.m_main_max_chunk_fallback = m_graph_index; // Always use the special LinearizationIndex(-1), indicating singleton chunk at end of // Cluster, here. if (!rename) graph.CreateChunkData(m_graph_index, LinearizationIndex(-1)); @@ -1792,10 +1817,8 @@ void TxGraphImpl::Compact() noexcept m_entries.pop_back(); } - // In a future commit, chunk information will end up containing a GraphIndex of the - // max-fallback transaction in the chunk. Since GraphIndex values may have been reassigned, we - // will need to recompute the chunk information (even if not IsAcceptable), so that the index - // order and comparisons remain consistent. + // Update the affected clusters, to fixup Entry::m_main_max_chunk_fallback values which may + // have become outdated due to the compaction above. std::sort(affected_main.begin(), affected_main.end()); affected_main.erase(std::unique(affected_main.begin(), affected_main.end()), affected_main.end()); for (Cluster* cluster : affected_main) { @@ -2655,6 +2678,10 @@ void TxGraphImpl::CommitStaging() noexcept // Staging must exist. Assume(m_staging_clusterset.has_value()); Assume(m_main_chunkindex_observers == 0); + // Get rid of removed transactions in staging before moving to main, so they do not need to be + // added to the chunk index there. Doing so is impossible if they were unlinked, and thus have + // no Ref anymore to pass to the fallback comparator. + ApplyRemovals(/*up_to_level=*/1); // Delete all conflicting Clusters in main, to make place for moving the staging ones // there. All of these have been copied to staging in PullIn(). auto conflicts = GetConflicts(); @@ -2841,6 +2868,7 @@ void GenericClusterImpl::SanityCheck(const TxGraphImpl& graph, int level) const if (!linchunking[chunk_num].transactions[lin_pos]) { // First transaction of a new chunk. ++chunk_num; + assert(chunk_num < linchunking.size()); chunk_pos = 0; if (linchunking[chunk_num].feerate << equal_feerate_prefix) { equal_feerate_prefix = linchunking[chunk_num].feerate; diff --git a/test/functional/mempool_packages.py b/test/functional/mempool_packages.py index ca6675d3316..a801dacebaa 100755 --- a/test/functional/mempool_packages.py +++ b/test/functional/mempool_packages.py @@ -239,9 +239,9 @@ class MempoolPackagesTest(BitcoinTestFramework): self.generate(self.nodes[0], 1) self.trigger_reorg(fork_blocks, self.nodes[0]) - # Check if the txs are returned to the mempool (though the transaction ordering may - # change as it is non-deterministic). - assert_equal(set(self.nodes[0].getrawmempool()), set(mempool0)) + # Check that the txs are returned to the mempool, and that transaction ordering is + # unchanged, as it is deterministic. + assert_equal(self.nodes[0].getrawmempool(), mempool0) # Clean-up the mempool self.generate(self.nodes[0], 1)