monero/tests/unit_tests/bulletproofs.cpp

317 lines
66 KiB
C++
Raw Normal View History

2019-03-05 14:05:34 -07:00
// Copyright (c) 2017-2019, The Monero Project
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other
// materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its contributors may be
// used to endorse or promote products derived from this software without specific
// prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
#include "gtest/gtest.h"
#include "string_tools.h"
2017-12-02 01:32:39 -07:00
#include "ringct/rctOps.h"
#include "ringct/rctSigs.h"
#include "ringct/bulletproofs.h"
#include "cryptonote_basic/blobdatatype.h"
#include "cryptonote_basic/cryptonote_format_utils.h"
#include "device/device.hpp"
#include "misc_log_ex.h"
TEST(bulletproofs, valid_zero)
{
rct::Bulletproof proof = bulletproof_PROVE(0, rct::skGen());
ASSERT_TRUE(rct::bulletproof_VERIFY(proof));
}
TEST(bulletproofs, valid_max)
{
rct::Bulletproof proof = bulletproof_PROVE(0xffffffffffffffff, rct::skGen());
ASSERT_TRUE(rct::bulletproof_VERIFY(proof));
}
TEST(bulletproofs, valid_random)
{
for (int n = 0; n < 8; ++n)
{
rct::Bulletproof proof = bulletproof_PROVE(crypto::rand<uint64_t>(), rct::skGen());
ASSERT_TRUE(rct::bulletproof_VERIFY(proof));
}
}
TEST(bulletproofs, valid_multi_random)
{
for (int n = 0; n < 8; ++n)
{
size_t outputs = 2 + n;
std::vector<uint64_t> amounts;
rct::keyV gamma;
for (size_t i = 0; i < outputs; ++i)
{
amounts.push_back(crypto::rand<uint64_t>());
gamma.push_back(rct::skGen());
}
rct::Bulletproof proof = bulletproof_PROVE(amounts, gamma);
ASSERT_TRUE(rct::bulletproof_VERIFY(proof));
}
}
TEST(bulletproofs, multi_splitting)
{
rct::ctkeyV sc, pc;
rct::ctkey sctmp, pctmp;
std::vector<unsigned int> index;
std::vector<uint64_t> inamounts, outamounts;
std::tie(sctmp, pctmp) = rct::ctskpkGen(6000);
sc.push_back(sctmp);
pc.push_back(pctmp);
inamounts.push_back(6000);
index.push_back(1);
std::tie(sctmp, pctmp) = rct::ctskpkGen(7000);
sc.push_back(sctmp);
pc.push_back(pctmp);
inamounts.push_back(7000);
index.push_back(1);
const int mixin = 3, max_outputs = 16;
for (int n_outputs = 1; n_outputs <= max_outputs; ++n_outputs)
{
std::vector<uint64_t> outamounts;
rct::keyV amount_keys;
rct::keyV destinations;
rct::key Sk, Pk;
uint64_t available = 6000 + 7000;
uint64_t amount;
rct::ctkeyM mixRing(sc.size());
//add output
for (size_t i = 0; i < n_outputs; ++i)
{
amount = rct::randXmrAmount(available);
outamounts.push_back(amount);
amount_keys.push_back(rct::hash_to_scalar(rct::zero()));
rct::skpkGen(Sk, Pk);
destinations.push_back(Pk);
available -= amount;
}
for (size_t i = 0; i < sc.size(); ++i)
{
for (size_t j = 0; j <= mixin; ++j)
{
if (j == 1)
mixRing[i].push_back(pc[i]);
else
mixRing[i].push_back({rct::scalarmultBase(rct::skGen()), rct::scalarmultBase(rct::skGen())});
}
}
rct::ctkeyV outSk;
rct::RCTConfig rct_config { rct::RangeProofPaddedBulletproof, 0 };
rct::rctSig s = rct::genRctSimple(rct::zero(), sc, destinations, inamounts, outamounts, available, mixRing, amount_keys, NULL, NULL, index, outSk, rct_config, hw::get_device("default"));
ASSERT_TRUE(rct::verRctSimple(s));
for (size_t i = 0; i < n_outputs; ++i)
{
rct::key mask;
rct::decodeRctSimple(s, amount_keys[i], i, mask, hw::get_device("default"));
ASSERT_TRUE(mask == outSk[i].mask);
}
}
}
TEST(bulletproofs, valid_aggregated)
{
static const size_t N_PROOFS = 8;
std::vector<rct::Bulletproof> proofs(N_PROOFS);
for (size_t n = 0; n < N_PROOFS; ++n)
{
size_t outputs = 2 + n;
std::vector<uint64_t> amounts;
rct::keyV gamma;
for (size_t i = 0; i < outputs; ++i)
{
amounts.push_back(crypto::rand<uint64_t>());
gamma.push_back(rct::skGen());
}
proofs[n] = bulletproof_PROVE(amounts, gamma);
}
ASSERT_TRUE(rct::bulletproof_VERIFY(proofs));
}
TEST(bulletproofs, invalid_8)
{
rct::key invalid_amount = rct::zero();
invalid_amount[8] = 1;
rct::Bulletproof proof = bulletproof_PROVE(invalid_amount, rct::skGen());
ASSERT_FALSE(rct::bulletproof_VERIFY(proof));
}
TEST(bulletproofs, invalid_31)
{
rct::key invalid_amount = rct::zero();
invalid_amount[31] = 1;
rct::Bulletproof proof = bulletproof_PROVE(invalid_amount, rct::skGen());
ASSERT_FALSE(rct::bulletproof_VERIFY(proof));
}
TEST(bulletproofs, invalid_gamma_0)
{
rct::key invalid_amount = rct::zero();
invalid_amount[8] = 1;
rct::key gamma = rct::zero();
rct::Bulletproof proof = bulletproof_PROVE(invalid_amount, gamma);
ASSERT_FALSE(rct::bulletproof_VERIFY(proof));
}
static const char * const torsion_elements[] =
{
"c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa",
"0000000000000000000000000000000000000000000000000000000000000000",
"26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc85",
"ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f",
"26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc05",
"0000000000000000000000000000000000000000000000000000000000000080",
"c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a",
};
TEST(bulletproofs, invalid_torsion)
{
rct::Bulletproof proof = bulletproof_PROVE(7329838943733, rct::skGen());
ASSERT_TRUE(rct::bulletproof_VERIFY(proof));
for (const auto &xs: torsion_elements)
{
rct::key x;
ASSERT_TRUE(epee::string_tools::hex_to_pod(xs, x));
ASSERT_FALSE(rct::isInMainSubgroup(x));
for (auto &k: proof.V)
{
const rct::key org_k = k;
rct::addKeys(k, org_k, x);
ASSERT_FALSE(rct::bulletproof_VERIFY(proof));
k = org_k;
}
for (auto &k: proof.L)
{
const rct::key org_k = k;
rct::addKeys(k, org_k, x);
ASSERT_FALSE(rct::bulletproof_VERIFY(proof));
k = org_k;
}
for (auto &k: proof.R)
{
const rct::key org_k = k;
rct::addKeys(k, org_k, x);
ASSERT_FALSE(rct::bulletproof_VERIFY(proof));
k = org_k;
}
const rct::key org_A = proof.A;
rct::addKeys(proof.A, org_A, x);
ASSERT_FALSE(rct::bulletproof_VERIFY(proof));
proof.A = org_A;
const rct::key org_S = proof.S;
rct::addKeys(proof.S, org_S, x);
ASSERT_FALSE(rct::bulletproof_VERIFY(proof));
proof.S = org_S;
const rct::key org_T1 = proof.T1;
rct::addKeys(proof.T1, org_T1, x);
ASSERT_FALSE(rct::bulletproof_VERIFY(proof));
proof.T1 = org_T1;
const rct::key org_T2 = proof.T2;
rct::addKeys(proof.T2, org_T2, x);
ASSERT_FALSE(rct::bulletproof_VERIFY(proof));
proof.T2 = org_T2;
}
}
TEST(bulletproof, weight_equal)
{
static const char *tx_hex = "02000102000b849b08f2b70b9891019707a8081bc7040d9f0b55d3019669afc83528a6e18454cf13ca392a581098c067df30e66dee8aaddf14c61a8f020002775faa070d3b3ab1d9de66deb402f635aca2580191bce277c26fef7c00cb3f3500025c9c10a978bfe085d42a7b73980f53eab4cbfde73d8023e21978ec8a467375e22101a340cd8bc95636a0ba6ffe5ebfda5eb637d44ad73c32150a469008cb870d22aa03d0cca632f376c5417327569d497d42f09386c5dd4b5efecd9dd20719861ef5aed810e70d824e8e77189c35e6d79993eeeea77b219106df29dd9e77370e7f2fb5ead175064ba8a59397a3ce6804bde23b4d90039c5ad4d1282bc23f791221bc185d70b30d84dda556348a3b9af09513946a03c190b9c53fbeb970a286b1ff8d462630ef0a2737ff40f238461e8ed3eedb8f2a01492abcb96e116ae9d51c4b35e9ba2f3bbe78228618f17a5708c0e30a47b7ed15d4a20ded508f9daddd92e07c6e74167cdf0100000099c4e562de6abd309b4cc26ab41aac39eb0eb252468f79bc5369eae8ba7f94ef2d795fb6b61a0e69e6a95dd3e257615188e80bc1c90c5f571028bb9d2b99c13d41a1e1a770e592ae7a9cda9014f6d4f3233d30f062b774a7241b6e0bb0b83b4a3e36200234a288fcf65cf8a35dfd7710dc5ece5d7abb5ec58451f1cbd41513b1bb6190c609c25e2a2b94eadfe22e8a9eb28ea3d16fa49cb1eb4d7f5c3706b50e7ae60cedf6af2c3e8dc8f96113c029749ae2b266090cc2e6650cf0a869f6c20b0792987702834ff278516dccbd3cff94a6ff36361178a302b37a62c9134b50739228430306ff2bc6a6d282d4cfa9bf6b92486f0e0dd594f2334296e248514c28436b3e86f9d527a8b1ed9f6ed09fa48514364df41d50cb3d376b71b3585cad9de30c465302ae91818ce42eb77e26a31242b4f1255f455df49409197a6d0e468f2c2d781684bb697a785ac77d41950901e9b67a2a4d6a3ec05fffec9e3a0313c972120ac3f5e01f1bc595438d7e07ff6de4ede96915a8696bcbaf449fae978565eceaebe2c3bd2f8315c535ff25fa8924fc2d49e0cb7ecc1c3fd72ce821513fa113078fda233e1588022c6267ba2f78a8a4f9ac8c7ea2dc4dca464902f46fb92702db8d26afa628f2aa182c2b34768a2b0581e7196ce041e73924af51d713db75093bf292e4263be8fc08a0b2f531e1a10ce79b95ab1fab726478cea8e79e0313ffc895069938ecf7ed14a037577f4f461ae6cde9bae6ade8a1d9e46040321b250d7ff9f3612b278757717596040dc58e7f68687b72c1ba71f36daeeb7ebdcbfd77d3518dff7d0fee252887ee38db33dffd714924d5823c539288d581eba17053beb273a13ca6f43132da705308bdc53c80c45e347bffb5c1fae7907369598660ce2c70d34083fec197b914c3b77f50e57ec54d89d0031df92a1241d40f9ea3ed14008ecc339323118ad22adca5c56687f854bc5fd47a3223016eee46e7d94b31a101df22d87b1404bbceaaaab2a8bde72aa318d3364e8926119d792cad21e51faf0cbd5ea0bbe939c5bcfbaa489dfda38aa124f3fc007b9e58f55ad8acd25d17a40bd4c1c17e03610fecb789702b0b8a4aa3a79028a7292212c550dec72f2c356f02bc0f2a0513ae07892143b8aa5ab30e9f6d71eeb3df2ea64a839b5b857000db043bf506a26953a909116b10cdce03a27d549db2f51f9a341c721bb0e442b5d0034038fbb0cd2ef27fb48f5acbd6b4104af18a98a1692d10d59884fcd2eb4641000ac32df57b5dcf387c4c097e5e7e702b2f07cdb18a69d5c69a5f7e135a9f8e020670758a1e4d955878de2f93181adfddd8cff4d20365c4663e870ff09d6b15065bbd81555d6aeb92e07ebbeae426cd0ab982a03ffeec31627ae140cd1e78f60ab6a55811d9d4051d50050c9e920e0b11c526530e613e0d3f925271f90ef0990e3df2c46170153e553a0035c0e8e87d957f40f072fd6b1ff30ee7aca3af88c40f1c255b3546dba9d23f352c729a0466729918336560df233843734e7dad57960f8d5592a299f6b762efdbd37aa0ff5310c940d03622023146a042079c8097fe01606594ab3578d0c0a90f8088d5c93504896ed80e809d22bf9483bf62398feb06099904cc23480b27709845ef1e26059d4730aeb5c2bb34c2ff34bff3c1a1c10a5898584fac078225bd435541fd2f4244e14118c8a08af7a3027d41b7af62420d12ba05466f905fe49882db44994180a1a549acfec42549254feda65aa6ee0c0e35e5a7525ae373ea0053fd536d4b6605ee833a0fa85e863807c30f02b46fde0305864da7d10f60b44ec1c2944a45de27912a39cebdc0ae18034397e4f5cfaf0ebe9ea5b225e80075f1bf6ac2211b7512870cc556e685a2464bf91100b36e5d0ea64af85d92d2aa1c2625e5bcbe93352a92dec8d735e54a2e6dfba6a91cc7c40e5c883d932769ce2d57b21ba898a2437ae6a39cfda1f3adefab0241548ad88104cbf113df4d1a243a5ae639b75169ae60b2c0dd1091a994e2a4d6d3536e3f4405a723c50ba4e9f822a2de189fd8158b0aa94c4b6255e5d4b504f789e4036d4206e8afd25693198f7bb3b04c23a6dc83f09260ae7c83726d4d524e7f9f851c39f5";
cryptonote::blobdata bd;
ASSERT_TRUE(epee::string_tools::parse_hexstr_to_binbuff(std::string(tx_hex), bd));
cryptonote::transaction tx;
crypto::hash tx_hash, tx_prefix_hash;
ASSERT_TRUE(parse_and_validate_tx_from_blob(bd, tx, tx_hash, tx_prefix_hash));
ASSERT_TRUE(tx.version == 2);
ASSERT_TRUE(rct::is_rct_bulletproof(tx.rct_signatures.type));
const uint64_t tx_size = bd.size();
const uint64_t tx_weight = cryptonote::get_transaction_weight(tx);
ASSERT_TRUE(tx_weight == tx_size); // it has two outputs, <= 2 makes weight == size
}
TEST(bulletproof, weight_more)
{
static const char *tx_hex = "02000102000be98714944aeb01c006c80cbd0aaa04e5023e9003fa089669afc83528a6e18454cf13ca392a581098c067df30e66dee8aaddf14c61a8f040002377a0483ad63d58e7667a8325349c89e41e9ad5dce5aef30204fd4a6dc8eb7a100022a518afc3d690a992150646c559a24add698c98e87e732244cf2855cb7d0cff10002485a8de9d099c96fce8f26ad320cd627a6bb188f719c380517861c031aa65011000218ebf7b40a5ba25fb98ad7c6543239c2a3343b9e7cfd5140280e587c8f930f0d2101b330267408724dcf7fc2902e7d74a7962995e7905cc5d043fa1c8c6379e0eccd03e089bb498d0fffca61afd0d61f4875e8b32fa63f8729c654bba5f167199b7b518433680242640504c7568d273b2a74fe2d204dbb97eea4724ee5a2cf19eb3349ec3a2602a244de2a33c62bbfaa0b4cb85bf36863f765b237138929e43462e4bf19684d0924fd73c30bee474f0e927e8eb84dd6cc987acaf41e19e2f1e07381bd95e0f504964c8d10793972e88d64683a4a3960a9645735a76cc62d99e7a87b62c3cb590ca9dc27f91e9103c1b55ece5d5a932a04c99bf019463455b5d78397bd2295be075af5ae9bf0e43e724e11f83f336ca3c1bd9601c7fd6642795e8618b5c5b9d0045a6766daf2118f994b418504c6939b94c72e875423989ea7069d73e8d02f7b0bd9c1c7eb2289eaeda5fabd8142ee0ebafcbe101c58e99034d0c9ca34a703180e1dd7000e9f11cb4bcbe11f0c0041a0cc30f5b8b3bd7f2ace0266dd0282aea17f088c88e98a22f764e32507d1c900ef50b1157b49dbfda2fd9a2ea3be5182fb10fa590b464907049d88ff9c33fbe6d8b05898abf196dd097e1009d9bd1a1997830100000006ccdcc8aa53e183578656540fa393e6d9f96c07497b9dd009b48e8f990a75be18f5f37a47ff07f3c4d6427626afc5d24897ad31a98d01cc44476fba41f6bc3dc3de91d2655130090393e3ebcb7f436470edefff5aa11fa1016fecccf1824a5cdd66ea51dcd8f0193a6e507309d6a13680605febb971c3df4cceac5078be996c0d686c72627696e6961447145143e23cae2c97686524c0587b6cce7b05851b087d658a795bd22de18c0f68e824e1673c47f4b7f4ba7d4bedd95f46ffc22d9409087a58a80088679d3775e46f75dc6dc48f485a2c35a8dd60e7dabe29f656cbaad8d25a5e01d165fa9df29acd6e2471c4880d3129fd110066788de9c979f03d9c2e46ab80bf0dbd24ac6aaba2db0d723e1ba3a002efd2aebf245a2fd53767fa490244396284826b64a4a3f069f21047486a27c5ebdf802c23d8d276b9c83fa2e329aefb953ad34f382975204706c14249a496791cd3d20f4bd98d8f6325f5e7d7aa2d1f8b23361434f74584136cf1ead94365a6ce134159141fa4c68660a99ad90caa8c711abe5411dffa7132f8ce71dba63619e1410380c56766c79ff8e433eb806f49bca6f1bcb0c66dfd61c3133e7c095a11abd068b6a5774a02a5825cbd82a408d5580ee4dbe9a4ba07282f5a764279ad27f7ac27e7cccb3c76b5dd64be7bbdf3ecc4abcc29bc561e81cbc502ed3a4ce277b567a6eb09dfd8454c4d4e8c038b9dd6042a0515b0d1dfbb45585e79ca5705a22fcb3c67bc0261cc0cec6998354448e83fa7ff8706178e14a482e73719df33c9d753757131f3560391be2dd6c40391e3e7882ea07bb23c4d2d157349965082e1447e94849fde224452f6c98efa44f6438b731859fac8f49761e4447e8d34275e7dd9ae01d8550dcc75284715e026d25e9c444265fb4fee3f783ff2a2a5c414714a57525738884bbdbd8d997dbbcafcafd8e283b524bef0ded141160f47ce352b2104257b312d12594de45a0241d9753ec19e2f8603b5fc8682d72bf1de51d7f4caa7026989a7e46b9dd41075ad480df9de6a952e8562e548e3576e9c9230cb2cd0ee7f955e2d29240d7fa55b8e0b0b6c92823d9636592c460af670bb0b8714ca626497c68403793fe8495a7542c60587d117e3adb3644e62053817fa600910e2dfad97b2a7492ac6fa13c0a9a03e0ce12c3d12a09a4e22b9d0d74b9d431d53252fcbd06cb119d128646042eef81002fc6e9ff5006e06247f40f0391ad095c0d50a78863c975edbf0498e58ba7e6e0505d5eaa4d8ba2aa3f40e728f1a6aef6b2f9f5705cc3d2591bb5b878c258b4107857dc6ee75d591ea7af7b16196cd6c979a0bf819db39658491889c83a41c2c0035116fcac23ac45144731592ea0e3a11c335a278b2a6798d46828c8590b92701468e9d9c3560ed58c3ab861995aca439ee49ecf4a5b0ad160a12bd23a437f90c383095e85a95bb441bcb8dc1752e805e85d1ee0f6967ce95dcd888efa7ac440813c78b11d56d2a1b870c59d36430b10cd28bc693c4f64e769acfbcff27d8e904e0ca7e73aab5439de571b66f91fe9c05264e070aa223b68e5de763d838985e0ec0e8ac0dd0b1f6eb1e145c4473f9edda5732b1f9d3627423b5c60e055377bd044ff30017d25b3d26b5590b53d8aeaf10ce73d86fe4c40fa14e6f710f72c7da0600e7fc495a75a875d1aeee246b70cf24a8a85fba2d31f96faa42ece112b9030987ce0e735ab51eb4222a48bc51ab69d644bda77fb2aa0cd3a0477a2a2d92510103dbd58ee1c28eb20cfb31f5268f4a70a431ff4aedbfdfc59ea6709283a51902202effba960da6170b1a25c26a52890da54757c93156d250540590266eed8c00647270cb302cff7cbe4a8ed27da21dbaa303d1aea0eb152e1f6fd24dbdfaea0c5b0f5d6acb6724cf711ec3194a94f52f8cce13e1e3d1d7758d3d7e3cd37fd1011265199eb4126975687ce958dd1a75b6a71cf397fb618003e85af842dc3f
cryptonote::blobdata bd;
ASSERT_TRUE(epee::string_tools::parse_hexstr_to_binbuff(std::string(tx_hex), bd));
cryptonote::transaction tx;
crypto::hash tx_hash, tx_prefix_hash;
ASSERT_TRUE(parse_and_validate_tx_from_blob(bd, tx, tx_hash, tx_prefix_hash));
ASSERT_TRUE(tx.version == 2);
ASSERT_TRUE(rct::is_rct_bulletproof(tx.rct_signatures.type));
const uint64_t tx_size = bd.size();
const uint64_t tx_weight = cryptonote::get_transaction_weight(tx);
ASSERT_TRUE(tx_weight > tx_size); // it has four outputs, > 2 makes weight > size
}
TEST(bulletproof, weight_pruned)
{
static const char * const txs_hex[] =
{
// 2->2 (typical)
"02000202000bc9d6cd05c8cb199bb00bfef406e29208c7ab01d70ca78601e40ed508bb0fa5858c58f39eadaeff740da417a8721c158a8b74446cfd39628f3e44b3080a8a02000be2addc049ee748b08f358bbe06b49511f2ec0cdfac02f113c3c201ed62ad1533ad1198960dafa30b71df46826f0e19d99cc718465064292c7405dd143f9e18020002e9b86613c898b464c638c1f937d2811941522faf84604b2d664828b0e5859c4b000261ee28891d33551894562400196c38c844b9e867c728c3e25a44337472172efe2c020901b07df06f3d45e1280193cebfe37edd96120ee381d84f9dd6139ef3a68b47fdcc4549347fa1a700510704f0f493612c0239a0a5f73c71d71cb2596cb122731a008d9ddd252096db9773b086feeffcf2365881cd4cee30339491cc0f5b61add935f3bdb71847034a133c8acafee411f231a8fd705c8d91f4e91a11c0eb1ce6013528d16db3c120bb5ad8444e114729aea47dcd2e5f378c49fe18d829c44e3cb9cf309e8fc4c745a7cce8879da7cf7cd339c0ee0143e63750550d8e3fa2e0fe23af89a8b88beb220be1cb71c8d3a6bdc67f1a413b104074e8ae2de7a8e9ff19a19ad1fdde269d81a1be8215d0cc91e327139a41252b755a7c15c28628ec60bdaa807c2c120641f3dc3fe56b3140814df319475d5f7e439916227d09e1d3b9ac07d695ece78befc1a28c73a0f1e276e976e6cef987b9a793170bc565c17344540c0700c1bebfdbeed6f6c9c88209094042a14499a2d0d336f6c62fd874cbf6b73277bbb54c7b426db3e9a7942770349985553567bb7655cc865e7a2bbba6ac3faf9dbb8bb541b6947018a6528db474a78cf71e3a299cec2d961ba9449c44a6faf9d00534ceaf5e2efa12a99959dd9dc47af47179738a744881132ce97471ada22f4c48fe632988044c5e333ca39e9417b84aaa25856534f0209eaa4e49b9157bb00daab935fa9a510a8548f370ff47453ddf7a07be9f75c1442e4f871f0fb429a2a62ae661f885acaf5882201c8339e978ed6e2de465124113dd1764d5134ee02509071a69a7c9eeed496c34a47f346b66c4bc76865e5e5ecf6adb5d4d98e5a1fa4dd71095e25c03f2d481411840e6a10fbbe5b263ebc811c358c1e18f0ed99d3767b5bf8ba710e06ad2515fde7171f4adc9733c743e28f64e38a5c83f6fa7d54869d05e55debb2b4809ced78ad63e98184b454b0b8bc389d8e31bb9fba67451f80c4551a0d47b71ace52a1665697ef2d1165ebef975425121e3458eeb51b4ad022de9ef0cec28919c7a36acb2306f5555c9fa4d69a66d4e2fc7b99ca358d547b6fc1d3a7a7a5e7bc2862873652539a6fb2dde97fdb66e3bbae24daf896aeb173359aad72ae6c0dc93510790c0199ed84e6a31649f388b9c7b117fa761626db88fcd0d2ce43378ec4263dbed27adb1c936c38ffd910e1a1e5345dd76fa1ccf9248d30d5d45f89d51114e2e0c802cc44ae136f91417165f9e5c8caab5e4d7de8f32390c4c32f4b6018728feb4865822f5efec9c3dc40e18aa4863cb63bddba3f981d508f5d05f1a4bae77623fc71507bf6d9b211b6c75c2255d00c12df0f76e6562000687490cac8cef84e8a4c6e20811912910b493a8b79e091c2d44546c44d358490a51103828dbaf5f2147e2c0269fd9cd4b104fef40c08127679bd90720f43f9d0c243dcc66e083b966419dad500f72d0dbcd5702f4c7becec255f11bf434bcf405d1dc321e7283d9df2c6f436af2837f3b13611e36c4ea548e9ee5786dbd30ac0f9d858b7cc6be8347fb99d37f0dcb06d9d1f5efbbc68fc3e11e8ca6db19b2a506b4672a36a8326db1d46f18928ca70338dc70581bf0c547c7c5a30b756108b602b257d70addf7018f8d622f89eb82354129fbb954cef36229058d13bf1f87f5011847e92170081e90fcfc6fed623fbb6c8b67ab132ff51876d08eed8bdacdd20302b7644a9d435376f89bddddf2577c7e92b2010034f9c8d7420c66bc37e7f60e13e3dade89bc76492da3176b1e7ed44463d27b8d289335179bbcc964a5fe72091ad35902c717b4d1c02b7523eeaed16c538d97c02c1226df7614d7763febda014b73a3b13882bb4664a4b00133e0aab894b4229536d42d82b4a311a3cb02f207d042e8ebb2128ab9de854450a49ee2cf02ad192ec763c9a4221a3d2f1539eb057e112031e612b0066fe2af774db0ab798b0fd708c06f70fd86182d43c2e4a50bd1ec0a0d8548249f52d88ed28bd9bb9ad1244f37d0d600c41c60e3887c04cf0b582f1de74787f38cbde4dba78a8e245b0273a8202c4981436321318928e5a30b38dd7d02b921703526816617c9eae06341df0161dfaff36396c22fe96c0e13083357e44232e505146c591503f0bf836e5213e8fbf10d8c8939ce53cf26959d060df317dd8a12dd865a815939fabce990f53f96b279a194e7b2f5edd4ce6316063a0c5c1b9128a026b8a602f9f6e5bcc1e8c3eb9e3ec4bbeeaf52a46ffe55ff07f47a776785f086fd46064987d89b8c651f316e768c8c4e934851b916994f45082bd216676b410c74ecfb9f72b49643dc26a1248a75a7bbfca63ef2855b855e0b12b0d8e9e510c5af09f34ac494ad8f7bc4f2938f8809bc62f763a10cb006740e798e0bf1812ba01afeb780a5245502734b723204cf39a64fe6d0b92e94cd8a0304eb112b618b5c3ce0c339d97a409a0c7462b55ca3e1f7224fba1c5a13df0f0e17c43e6e08a41a31e948a04de710d984055f0b487c623d96290ca8a76adbb703e524da741d2a1924c5ebb8fd378409ceb7e5d8a9f92c990e8a3e4cc7a8b0c10582243059653b4b37869cb07a6764212ad51600f5c84ac3e38529ee8a7dd0d006ca15f7b92ffab6bcfa507a4af1
// 6->2 (> 2 inputs)
"02000602000b81948105838048aad812f5981896fb0b839604f8263298039c016ae38f312bdfeaa5e8a61caeba81e5c4bee74de8c5fe13a19f6fda77cb1eceef3c02000bccceca05eca715bea71e86d804d354f518ce3b9d04aa15fa088c02c70a136784ecea98d8572a1505e1ad41c2bb5814ade5f177c3c822995debec2702000bc5e39104db84ac01858e26c0de1ac2f702cef2019c14fc30f1042fdf1dbd8556415960e14fc114000c6f8df7c5f7708ef4881cf988a63ebbf9d6093e4102000b85daaa05ea90508ab001b78a02d0b3019f3ae0e902d68001f90e8115c221b766e3317045167b1f89c50feccea2cb42cacbb6de1b63fe5d3cca7139cc5a1a02000bae95fe04b5908101faca018ad701fb93018b078f06c62e9f1cc90b830497bb03346d9d6c9166e1c296c70098fec034422bdf375cfbd8bd17c961c5a19602000bbeaef604e18e3bdeb03bc69302fbe710c5fc01d328aaae01ba669304b60d4d8717f1c299dbdf549023d365c9262b880836cb4715040a7dfefbdd22148413020002b2594f0d949b9dcf69700396ac276f54457d04351ec911556d92cb2dd4c6377000027909dce6fb3aea41098894bccc894c9998ec6d4b7b8a48b2ea56e4550d64cf94440100ed16b0c76425fcd895875c77799cdb53d0774f8281246bfd74ed8d682c4bff02210028d666c408ed604e5d641752a318946c38e3c7ff592200cd393fba3d9fc12a720490eb9c2bb3a8ba73a31c997dc7fb88f47fd7a8e3fb6bebe010ebce3d95cd7902c8ac5046857831a396d4d85c991d0fe5e0376018fc88f81c495a8b2a29b9668f91b2d7857545090a8b6a1f4172e2a272ab889b6b01f14efa280434afd1dd3990dfd39c102a69e2c06bb418b6741718ba3556c181b2c0c0da2f79fa536e7fe0bd1132608e38d63b6c047fbcb4ec9b7a75eba19af0122b8ee529d97a9d9957af9320b2ea50601964fcf6a798f8e24a7df89bbd4acf986fc89e9d9dfcf86ce213c55be591e26066202e20a599bee2551737a7c97d841b86adf4c4ae88aa69b4391eebac6e191a123a5e396a552bb31e0013ab3bbeed00a69de7d068b59db9fe22730e1e8ef9c10de4dc65e4e688ca2aa8be8443f6cf0b078537dc76f453fe7ff0e0762a397654f4c8a2e9218a473f8caf3acf4195dea623327748695dc77bde022372b1f2aca9ff1072c7aa6df75a34bc601b3b45c89fd8d3d273b74b80e0318dc601c286b02fc3b734563beea2ee0e266bd73cc1d1bfb50a6dd83013e1a0ad82fac574acabc375b93521937957e6900c213e5846da4693114dd2ffeebd2f959f03cc1063711edd465ab3b10850e787c93db003e6832596c611e38df6de4e9ac3cc17a28272a6d9b7948755e053fd327196098594efaa45f56e63f31eb18b4e27b4a05c2301dc2702b8e8c61c8974123131cfb540848d1107bf2a2489109cb3b7d2cf08f60a93b67df503524b95b126a47a35b28c7d88be3d4bd882ba35f2a4ae88c9de5df5c2922ce5304aabc18387952b3e2a81833e00b5b3a96940dbfd3c4fdf59001d46e8abc1d09f1272c0a4c6041d695e70023c717bb74d43b8ac580d32a707d893798250ba7e8ae2ab635cd94a014dba0a52e78eb23f3bf554e05e0686fdb8ae33032b0b9a7588fc2d24adaa5b77930421e1c9ce12d497fb9999e9bc24956087925d960f1e9863bdebcf518f5e82bce90d82da60eee7ef03b73787c29f6a94b97086f65459d3bee486aef0059030ba9c8b4b1ef7544797ca8301a1b7e49b9047cf5836e67d1b8d0f9958c457a2de8b667326100e019df5cbff2dcf660ec96d425ddc31cbfe5f7a92e921d572d9c317e05681f5fa0e96e48d7e5de965969dd1c76ced1de6e6b85b21d36cc6c97848fe812743156a0354ceda958787241269899629e46a8351dcf6d9895e2f14ef81158cdf69f64f0962f6faf8169da2a41665c97f0021786909aa00b841b2733d5b9aadbb20179d0a1fcee659997eb605bfbca99d25a93e81b38d92c26709ce339fbf1a854afddb0c0e8f16e803534152f4ac7a1311e5099294eea4a54a6fdb52469366aab93a610199806046522e24f6884283c003d45b1e96514ebeb95f1899bca85dc09037e40b98e42f43a06d5373ca21e6a04f39dc1b3df7a7d3be160126701fcf325b7daa0101d133aae87eba25f724ad9bec61674f09d53bf29d9bc4a9c59f5c0e89d93f01b2ebbcef3fdb3428d77f75108de6545442aeedbe0784b9262326d9467354fc09ff26344b4705ec4d0faa7d9e1e4bcef207dec33f0c4c72b300c06ced264ca10b2fdd6c37bc8858f2682dfbdd193a2289b51d7ceafdaf5b5d08c288b621dbd900a7212c6799968afe6bd5734666c3ba0ac76986d2f2b54e784a69246351386306fd6c9a595e43d6ebd40c9dbc3d385d4fe2a39d83a0c1e676f14da53cfc65db0637063d7a335bb7bce84a21ecebafdc7f376865660f78ce682fde76a89f07e800c00bf162f40af6d1f28bf600b589fdc27bc8120c0faa009ac6f3ed0f31361d05287d159526b5c3972b786e43829468b4bc06710975b6f673e931a8ce9c263f044f2dd71119d55086cb421585337d39550374df46b09a785c018a30b340e71308d3cc92b780f5562153b069be6fbf2a3043b441c478c84de4abeafc48ec4fd008dda3f78bfdac42a2b6c33c2bb7836fdcec147897ddd4532cf357cfdd2fc5a100dd802f6c35ecb3d42017326e0ac5f4a80ad9cd7aa084639217373ba4d5178e0c6b7a8010e6e398d880d555962aa5e12036d3c73cf114a4662bd79bc2a3f13c088f67b9075af6f0623b02e51f63d3c781fd13cef958f7949a34792f81c882e405fad08ed668693979347c08c5a82f57b57c2c39461c0975cc0e0a
// 2->4 (> 2 outputs, without padding)
"02000202000ba5f1fa05f7ea04efd302fd6ee47cd80cd208910bae060454f56a3e51002614f2b54226640672a4511b84e668e612da8405b8783ce45da13e02000beceffa05e18901b49302978603e24bb1b901c463bf0ade04dc098829991755888c64d20ebe593bfafa5ecdc08a82c56afa5cc1c0c1d2c972d35cbb3704000225ede2c23e774a1b90ef90ad1322cafa78765e2f4222f628184bb7c73c1db84600026320e36863071fa8443f916120f5b21833a31f2200b6755a6e6265dbd5990b1700024ca4d3ef20b4739f81bf5cbcc9463c27e9fe206ce5889ffe81b838a7d6877a9400029679317f62907bca73f75d7996cb5add23c3fbef473b3d06ead088cb9d8e6e14a30101003473d2ba95bbc49657ee50d75b78c346c3935e9ff7b93a8c8e1cd876790e180404dc6d8a0a7f715dbea82a9927d05f73d74b9a396d7816b931287ade73743a24ad9ada327a6eb10ae019d1bc2cb92ac42cf644b00a95e462567b89810b54056fc3eda791ec86d4de847413466bb4eedd0a9bd2679422624b3cdafbff235b1d26dd22ec16b4215b854b4e3fde48624768f91dc3651971a7c83ac8d0e1b70d943eac04f0859619f436531d60f73c5e596a9655fc478377f0768f307d97b4c94f1e1c08e6352ee272bb99c3bf79b2d826a6f33ee162afb1d61ae36deff0883fd8405af667a1911cfe074af2d8d16617d6da9c6086cdbae8faa8a3baae67dc9e9d52b5c4c003fdb4b99516d68a119998b5ebba373d83a3fc01933595ca9005df0febebb1135d5086db6a8f5d9602e7a7d9a63da04dfde998da5389704526be09891197a94d02dc9801964dbeaa761f597d3b88400384bf620ad1d6073198f1407016de24f28c6430054d3b52810d5ed73a46a45d054cbaea3f8e504d211b3a6bbf3378326971ecb59f25ccfc27594e0df064bac5244f7269b03f90a62e5c94bbf1047df4cb65912a6efaa61197cf432672e914b7514acd34c6aa3ec6ea77163134c970f0b62f03a7ca2afb6b88b26a6b93b161702d376c2893a27ff010094ab01b8b09a6776fba4a032ad443b13a555dc98e8ba277910aba283f44a05176d6c660671e118e56ffe008087514b9995f35835ff90dc71739ba53f14450c45b36adb88f207a7e0cd673abf5ee603e49d31624a992259ff30c44795d85ca0e848b5bd51443753d1c5a746138da9afd6ada84d864b49e97b1ae94d084eb99d4bc0d90eb4a4e3ece29222f5c3f48c8824cc6883765ac049a8bf17fff16d82dca8a7ce13b8c0ff7758a5f7b2c320e88c001d66f3de3f82a9332bae8e2f70041f4b4090412b891d91668e24d1a0631b1846bccfabb606f609123264dcea9b2db846582eb691576e6135c438ca149385fd0acbcbdf8311fc933a5d3cb34c581ec6927cea22965533d500e139e3733c08007f07f169d14b5e6aa4536a0f4939178c42e07515e1fcde9d709666c294b08ac04d1ce517ce0ef40c045724676d010df1727bd21e99d05acee37af096ac609f91f78781ad1f5592068ec094948fcf55c18dec55354073a974bdba583d5405054bf364367488d885636742c1f0fcf3a09b1c3e9badfffef05fa743cd32c176a8c39696636f4c7d1968a5a1af166f251da120f7afccca73373c16300f58cfef4cf037220f8f4df81300787dd8dd4e0a80963734546db1f6b199cfe20a5b487c1945cc8d987405a62398509b7347f00ab2f01d3b2070eb2bfeb382f0ec34d79fed9480ea7b6f7c8e3d773ea906f36894febcc86b13ad1320182cfee0c7f3ce6d281e2c264e0ad493ba2426e67873fd27f2b6ba15d1f5e2dcaf3033b774d0cda8609a7c3a4b9c8489a42c9bdabd8048fa0f10da77211b808b0514cbaa1a069ba0507a9586bda713f7153f165babaa51e2ab1293457a38ff578381fcde6d511940417c57e616e2563b08d620f2ead09e0d982364391d97dbbe250eacb724180670062881c87d12598a9516790079e2269766e23864a50fbd3db7ae0908049dd1b0240aee26b3287c4949e3aa38ec3cf7b95cc42d90850169af66ba70a18ee7bac0da9d9d00ee152707d95e742d2ddaa976dd7e5a77d3bee16c15267096c7d393b03a6864edc60eed09b528fc459baad4e8b5330b14e0c4a0c8bd3ce490638a10b0306752fc112fd30afbba7e9b4c52bbe1f4c666a025e3092d2378c5761237344071f5411d5ed724de7a802e9c386d872973aaab2a464e1b692035303002bb1b20a6eba6b5c45a504f061e0c4b60890f086c02fc07ea91628e12b11ab77ee56fb06af1a8e2e2700fe2f732a577580b09944c7549232b81265317abba6d553020f028184684c3ad74c74020676e8042891ae52db0795e647660566551ad47b20830e98a1780b0cc723e28eaaa42d5245499aded7290638aa638a47771323a72ee4067b757c4e4528e2bb1545ee7c63eed75155b8f21247c69c498974732935803c0ddb38c79ff35b3360ef54c66d0978fd7119ff7c913e783be3ef7a35b8840c5e0bb2e8a76f62d048d17bbc2463691f2012e6aabf4556d7d4df358a36c221522207966c8ef17a80fd37d0ae58999e69c5f834513df1e864659729a29fca5c338b02c993f776107a8b4a4c41fbc4e388510db48d9f66a670e8790e24be6334b9e6009868fb3815ea040e1ecf2ca9e2d5239ec57f52d65490618181ec51219da8210fec04e5eec270ad6a023d29e88d7c4b70c3052b5d6b9d31d2e3c106fc5bdd6a0c4707abd793644ca791ec1ca2c2ab5b6a829da8c40185e0ca712c11699a78bd051b9498e7b1e8db95f43c65c2aaaca7dfab2995ed05176cd4cfd196470e5b8c0f3cb541d16d0fd55651d666648f9762ab24bd5f52e1ba2b1a6ed6a730fa8fa00dd80da44e48067d4bda00
// 1->3 (single input, > 2 outputs, padding needed)
"02000102000bd192e40587e41cafd601bd14ad7b8934a70b8a08c901d002b218e57d06d6bf3edcd4c8baf1fb6ba7e3bab9ae6c861d37130cb18084900738cd9b03000267ba3796b4fa651f3f1d3b872d0fcf71b553269b65862b99abe46be097f1661c00028e003bf7aa08e952e98c11f2bd182544301388eaac17025a65c28092c3b175440002af9ebba77369e67aebc6bd0dde1e33e0bb2be82e6a708545ed956f879e4af4df8301012e289573739aab1e9155c79f625f0f9977b3323e0191ec04708a4e15601737720403e671cea6b65905819d5fdb011d6f60b95caad5962b2f57b748bf76be03aaebac5e573303c2fdbf1cb72aadaddb11041dcbab648b84dd7c43bfc2be9f721decc37fbb05dd329c5df09463a3f0f70dff02e9c276ea0d81d7ea75faaac76b8d0b0a0480c2b112c404e464a330f78c8571322b7aa91741fe65418cc4b3d320e7e047039840c790c8d442d667e08e3024d9c5aec19f3b2f84d957cee66a2a8ae83261fdd8cedb5dc032a87a5aec5b5eade9c2014774c4796d955cd0bafd8a49d0266a5fb8ca7487658e762a8f4528e3f9b61d360169fec90ab618c69ad9fb4f011a60bddd7d5435b6a9f8bf98b90d4a5539fa12185f5afbd7363e869b1734741db610b2f18b4d6e962eceb036e5dbc7e065524a95bc1cf07e42b7ca8dc9cb3d053acf2b66f385ee2bd38a222627a87ad382d2b2ff65f06af88dd20cadf5c31f2cb33673fde7a4726b1e25c443fc954f7cde13daccc8ba0021c4f79fcdd5a466cae851a2e18ffeae9ef3b47f0139d48e6e8818cb653ae029fd39d4fef26cd958038ba88d509315801ec86320ca7b2db37b106fb24686a2b2b6de5dbf9e20412b0f087ce3f09bf9f6b4dad9d8f5e655904c1a95bc0df434c46368a8012a1f66fe7b819dcbfd4c04c369bfbd727f9fd048f344e30e9276fdffad0469a0478754d30e0f69c4b156c8d3ead274b52ce491d504fd2a0f5f5911f4b90867133e8a18a96c28aca99729b639e95bfa7361a4fc036725f495ade4d9cdf8df8b5d6c44b4c91c4a905434257b96d171310457c22c382cce306614b77c6f502e4080e81aa97c279a46a9271728ba8078ec2aeec5e7bfac59b027dd1e601c6de7be18663090567ce66698ae6ce7cf2a6e9ca0d602654bc14d0856c240f1cacc87e558b547547dd7ffbb90f11444522917a0306569fec9e99adc1c4f427a25d494910d759db0ee0dd00852dc75cb9ae8e3154d3281851fcf447e5f013e6f4356ca88cd7465a09d7c9b7fad8d62c9eaff44debe17b6bac31f771a58df4b6adc3dbc3a42c4312e65167aac31d347d16a68292569ce00eb91b1069abb130d1cb02a94f43309fb5c719cd2eb28194d49a559a8e694a87cf6575434ecf9019b0f4a308f272ebf9bf6e379acf09341eefafd0fc8632c39fc6734bdd6438a146221b81b66b7622f67e3387a511d2d6e1401ac0103287beb2a4f08b0af134b58f1b58eeb90c298e70f9d5b23a90508815e73408e51f64c0bf0f0c48742d7574b1e16811a9c054829e5d459e35beb7ef0a99d6cc37872130c6353ad83b10437222f9276f9e4d14bb4c5e3d8dd569e8de22966707fbd64210bd5b004b18cd5ffb1d33dfd9124f74a7d8ae7e81fe50befd4f4ac74899b601e359c6d2e9b10bdd2b97d2f6c6f5cada485c81d4f612603cefce0edf7781a39590c5f3c186bd782608e21c218593e9655d9100f3d000f0c14b94ba59430e4b80a6226408b10b2e2ed2baa279a0138dc867e5a167235a702fdd1ba8c8bce93a7c35b9c14af24189eb07d5b3e5d1a56c0e0c76a6981dfca073a15e3710594607f5211e61449ac4b0a35f07906497b87ea3c0fd217b7e0bc02568fa6022064ce6059216a0fcb614cd43dbdff65db89784d8c14834593564805fce3f7183d245efda6dce9cb3969e39d9416cdfc62e131a2e4ccd3b4a255800d8643cc61689d67f782727eaa27ab1803fa7f59b765d96899c586881a1cbcb70410fbf62208ceba2312e816fce9b9e8bf323feb60f3a711301880970193e49f0dc0234844078892959b54574fd318d74b50cd5c6a095f2c0135e822293d3f8c03de3fc9c1b3ec9c76e1000aa9fcc0855ba9f58a4286fd2d072b92c5f9fcd4f50f0986a1bdaf87d080ee7731d584feaf653e9a81097b6f53bc48ffe8af9caaae0645c6b8a61631dd23cee2416df5e8b0c19e26bef3b820dcbe263ef357e7adfa0721346b01555e95975b521003cfbbe9bc0ddf7b2ccc419b395513a9a86aefba0a87379a2197df2a8d18d3858226a17fbf6ac9c6d4d780eaf6e9c415927a346d08758a4877b0ffc2e9628bde7a71cd32c350b7beaf464f61f1e09a77fcfb7bdf094d07431a14240aa76b1075043e1027817c905e4019d189cce16520f32f659e0124aa055d6b83be211eea3b47a0346229e6f1caefe1641944baca14816b41870eeda213b2d05ec79096ee1baea557b2e9fa95335262a9dec9616019c6f80e70064a5dd936c7a28eba7c51d952bce0c25d6c079aa994703f39dc8c3c2e870c7a0e015287b9c3a0ddb5db34378e7f2562bbe1e37eac1cd2ca60ba9cc2e59593ac0f0de326b04c0b049bf5a2d5288f189b33244bbcff223b22da63bee884493b900206ea1daa55641f45081d2e99dbefae6786a28ed37170cbc1135add1cf2fae80c96254baa76bfb24b4cc45a76bd37b07be8362f7915e52b16710688c7b9b35d0ad5685d723167a135508f52e7974415d1bc35035f753c7bf5dc0a69b3a1a6060701e7e092a5628a646f00203decb6b1b05525dd9d752884d2a0b537d26bd78c71",
// 2->16 (max number of outputs)
"02000202000bc9859604c9f88601a4d840decb1c9fd404b46b9bb901eaf902dc1ab00c325fcfc28bc7ee06fa5d29214133a97e496fba9ba36b74233adad17c97ae25594202000b97d8bf05dcce33e9e20ee319faa501a20c8123a732fa06c904c2062b2cba1976cafb8d959bb16b81d6445f170904ebe85a6bbfcb003e2e1a3af265100002b20b0c3580b4d8d9d358b96f2cf8982dfe8b4f2807dbabfc239e84250fa7d14400026379c1ff6cd521817c0eb4f4eb12d436587354cb4a55ee48bd74f76b32c2a68c0002a1118d46c298cb369902855a917789fdbbff1da9fff7888a7b4647f1a6cf07bd00020ef0267304ee016be4d390bd79611a278ffbdd78857557e5907fb2e436bbe6d9000203234b35c686b6a361a960f5f632388b8000d385fc252fc5409cbfe766c4da80000265a959e7af26558b92bac9b151b0de2d13b282ca56dbdf1b78b7c0d5ee4f2ec10002b1e79cc58f13dd1f8298e1daaca827f927f927b7a8ecbdf428a75028acc669820002f722a9ae0712aefc5722193a7128594588c211f98c72f4d8c97bc59a9daddad9000252d691659f17c75ebc56ef148f49c618d6aef367f0e70fc987cfee05e586e8f900029a164805f660d9449336a04f053dbff9dd17716e6fb6e2446f3f84d7bdacd796000292b1c7b3e87ed9ada9d1b27c072520eb5c981b90df30922f5872b0a2926f78970002512fbcf506e6c4a8274fc392579df36b19d85fa820f849b88d76db3b492481200002136c4820d1888891523313db879bb52b710ffd40e2005ceda0b79fd9f84aff2d00026c69fd01aa02af832784f7339f40e84606d9dcad39e1424f118d83a3a44e49fd00021f383838b23056206c5291e000e603a3941e275daef67cf9cde5e44ce2f70f3a00028f6a118dfb496a952a5aa04f24fa82bf01be9387de230bf47f234263dbc65630a304011ab917afbf8ccebec17a70f313d7fb7d38b34a9e531c621788259c1f7d6c10310410970987be37d16faca23306b4e6623b1589efc18e796b19da792ed6fadb621168a28224ccb4ba5656b128570c0652ead24157fb680326e3ef9b8574ca0616d7c0815e002fd2ccf72ecf02583bb420e251220a31e80e5a2072aedec3fdad3a5b06964862de7596b79b689ed606907750910c5e118ebef44661e61c45c0ddf6fa1a68caa136e17fde5bdd667931e9f091c670e9ccf2393597567d449412aff4cee7dd0e39fb4eb36bd7db0899bc074afb427f8262240cba11209d70d0d1324c63d850f636a5afc0939a4e2f87913aa1f2bd0a443ed205556b663d448dbc41cb2d016cc3afb69d24c9b956be4de58d619f90855ca4be52595f248fe115910a3fd10dba6856e7bcd8635305ce0499a7be538f274efce6b5fbd2e1c5a11d3cab785313170f1a59c91ee7b92b060e6b44f2076034a4aef1dc1136c573043c1b23c0f3fff52eafe964f39ce301ae309f61ccf6dacf2a6bcbda3747f9b068c51cec5ef5e9be2eaae1f83188576e09ca3a0fcd72e25c2d3fd51309d64fe566a088e0515568f20792ac9b0dc042f7b2cfb6bdace66e40cf4675e3e0696f401df692881902427e7cb04db521998d1ab503f4b11d424e7571a1cb0d9c7abc757ac39892a129f291bdb2cb875994cd421d02f571a45f7ce5645dfcd2d8166b3b9507544f4d01e316a8d04b762dd27a6f8332b44f118eaf28105e3dad185e615830193c59fbfa1b04a088a43ceae54f1a27e4153ca9e6389653df0808f4cc6e4e7ec65ebc7eabd0715dc4bc7cebfffb3cee6f661010ae9db23970315f4be52e4e9eee129f3466e704aa0b8fbdab113949240d8dd18cb408d3357888af0a536c7413322bcef49326ed64a314cc0dada03d50e13c93715ffe7110c87ee337c525bd54198170c83d49f0556d5cad3bae98e643d01db86385079d3bf39bbf3b408b2bec59a2842d5cee2cf96aee715659deaf0510bb7d1d91346158616c3c0f777b9290be6b1e0e4295970daa05e5a355870c4b9f5ca12836c5a047d07b763ae4b7276d1690cc13419a7060e4ed9d684267f7077f72dcd5a0157c06c68041d7c622a6409f3a064abf921e3247dfc1bb7dd621b2092c2ec66fe0ce7e7172dd308a28ba11d650efe17f62dd9db6edf9e67e0fcb0fbfbea120139e0e2614b0196715aac42b3b98172b2d0d8ff64d4ef5f21c29c0539f7e383bb2680483ecd2154aee9a14f4d91f465f1a31e6c6432cc5df0b7ea88d5df05096dc4edafdf6973bf2af634b8bf92de9c672e4db05d91fe1ad5418e9260a1914eeebf2b62b45aff942e73f6585c46aa641092b0f02047869530753720125917afd1842e154db7fa12ceb3b0644f65f20cbd8dfb2061eaa7d8ddd8a78dbf4fc0ffa8afd182c5d959c07dc81b91ac97e179256e548564c46b33036ad083a964473e2b33291e26c7fb3b89ff49076eb73ec6966f9903512f0778fc98d734bbcabafb9e42c0d246c9ac8d7d612e640aae66e9c3b3fb1cec97f2fc67a34bf4d28c0065756882bc20439eae01c9dd7e7d857e6c3a359d71c7d1c360b59ad6738e94b5d09ad3adbd09dd72cced13a2ff39d8774cddebb4ac0090d1b6336eba34e2647fa99bca6c25a6d8a9eaf256b5e815034fdc5427397728fe23b0108b14a904aae5bf6dc8e6dfd19a820c0dc23cf5d092248c91587e39b7b922e2371104d5d7f484d2414e747bf1fe9f850656e446d8213ea67973e940202a6d7e68e3412dac848c4c8b62fac5bd9cb45d449dd478b1cccf0e7871a38707bbc676fe40ccf0be8691f7897f1d320a6197a77bdc3e49799d6bd65f9f56217d1117bc1429da799dbc50146c9460372c335d8e67d924572a8d4458f4bda5eae98d0aa0ff9261b00a1f648aebbc51ddfb6d296
// 5->16 (all above typical)
"02000502000b8781fe05fb8505f311ed18b544fb0c950db40dfd04a4028209e817f06867fac336950fb89e3129c9955ff659005760cfe92c9d023649fef3b602000bafe8c002d6b9bf03c64ee70eda70e149d745c76ea01ab61dc80777d6fc03adf0aba02a75366390022d5d76fb292f2845eca286a3d3b99366db6302000bd3dc8b04c5c1609bcf4e8ba641a89705f42be47ddd20f0af018708f3065465b6be9996bd2b5857aa549a8560a46c1fc6445492c40e537efbc54609f76402000b9cfae504f8b18e0187d60181ca06e0c903b507c947d23383b8018b05e4810149490c1fe8dcc7078be48b221aabe66739dbd8881472f8b7d4ce7db96abd741102000bdb9208a9cd5a81a685048aa51f8da0758db006987e9d12d6069312c90c2d9fb7322a630ff1aee961f47d5ceef8f07f8414997a30db528910cf75d3972a10000247e43bd7fe853540030322fb4ab85689ddaa9c43449828de6320e5779d4c07fe0002a50430c2b0f47b244bdd56005f4b1154ede39e747c87333e3dc318f22d301a940002033eeb91b921e2588891195d65fc2e0778e8ed89f7fe7abad5664bf0db8823700002fc895247b38b45094f5de7fe09846e06572eaae07db010bda33cde5b044ec0be0002163a8fbb3f93e2afc8ab105802af4bef995c5f0a6f193b074191b63614f575810002cfc077c6423c8efff931fa807bf5b49912aed82c460bef8b5f99f6d1fc0e400d00022f1725b732410c5d8aa66901fbc7bbf23a8de5ea79cb81ea221f7271d3e47cd00002fed7a5de3d56c5211786b3de96631ac0fa04aee51a86639bf24dad0e8ec1f44c00028c75d0e5c572395f683186e974060271ec671a3b2bcf8063713638b5b15700000002fb4a6c5b0b2f9d479647274a34c9833cae226132439d42712d34cc10ae1338cb0002c4c8fdf55fa47537fb82c6055fe2e6527cf2d702665990517d3df536d25215aa000258536aee1c079aa491c9cfbcd2d9c8249608b0a762a0caffbafbe37a6c2cc70700025bf3d530fc34a1082a4e82ad6995433f94f7dde43d6c7de3324167bf452f519300020faad97522f3c86dcbdf2c2dc971b56604a5383bb4f46693e57453194e6155150002af2e9efd2755487f33d55734bd3b1ce46ac9b02fa24ddc7661a03d46d2a2a86000029da94d4156c3f6cb7ee14127ddf6253756cf473f59921c6b44cc1ecdff205bfaa304015c9f74360a58b2ada93db219cb9c4512ccb6a07d05c45e24e81788b71d4f98a20410c69026363266539808f0c29a8db86986b35d092269727c299d98f4a172557bf36d84efc1776c1578a781ebd76f76c16b793f8fe712a0828a697a2636e3b6e2c556be601a7aafa26bd70379385f0931ab6584a84c9e2a5f6def804bd1c9faa245b7062845e590676b545dd36952834b90b2d87e14f9edc98dc2c12891e0dcfaa2e7ac311c2ee09e780c28b4c98c4f5b996ba28037c5e4506eca4e39720ab7c2e6ed7a8ac08ae9ffb43e780f4d03bcdf30a79ddc607de1862551abe70b7ebd513041d3ff8ac51830c04385e3de7629b06c44936f3aba6490aa5fa27be7d2dedc54d6514c742919d6919b0bc83e0d7dd4889c1d576ad26ae8d60467a2f15994cc73bef97a2c65f3a35c9fbdac19b1696f966ddf61fbafd8e7e0185ff5b60f5174057b765bec3b01a455703697c19bf9ecd5a9e25ff3e172f2e757e49fc3c3c4b36880559814faf6e8b277d9c2c72aec65ff461c84eb2a97fa5cbece0ac860fbd01809dce5c8c2f1bb296ab9ac266bf455a8c0c6892c410473190a3e9ffb686cef4af7c1ad24b0106c461bf9f3cddf8900b29f79099e9e474171d4997f562535f18e87e322f7fc3ee89de1d5b197e1334e2614b8562470b27f02919cc40a4c931413aeebfac18b68be1a8a29637a356d85073b44d2e091781b76eaffca6c965a599573a7102630bf196ee5fb937921cfcfdaa5a7136ab3a4371db257136f8a841a8104c0deaf4eb744a642028e28f90a377c86a79351ff7d995245d51a698861488cf4fc61aff3f7234974eb4890c17c3d64332e131922e1085e6e543c47654aa7ef5cc9dbf51e0ce58abc843b9c03399a174b432d86da7e1092766064f1fc07f79f8a04423664b13ffd8c0b489390ab9a184d8c049c0c68d1e5c9bf1a77a8904e80e2dac395babdb7079957d5a03b062e16939fb13ac6e1d97817f1715ad3154c519cd576b19bb9ce28b4865f777caf81aeb48406e93686e8a9298acbfae212a4cebfb2871c1d78c1ae05925e66529f43cdb2423d16d465a3c2a8a3c85f17842695bb8d51403034cea7755f6047801f46751a3f2582a867483c9e15f05abde536eeb28a2e267d8ce153f9a6ca2e44317a777e9f75e709e487e450b8c0b78dc99e5d58c3abb84a857eac5f51e75ebfa59a84508a88adfba6d6cf0e02fbc33308c5283c0b237dc7fbb6a84636322b2d2371ca48159d0c61d89a3b5d1aa32752a2d7cb37f2182751cf3ca458b24239bdecfb852515d1fbaa9f23b020dbb4b7777bffb330ac438175bb37b03752f1105ee437ea9b2795275fbe9827ed00944fccb01fbaf6ca66877b3951d6475eb68d419cd9e8aaae49d339aab5caeb89a6011623a4872e8305f6b6e9dffab2fa46f330371bb1ec9bd5618a0b3696243e2bc91265789723441169e7cec7d0418a91d383185681b9cd12636bb250660c7c9df18068b7a3570d54e3634404e1eb5e150a34a22c2b5d07fc1c2b1bdcbd2f8192997063ef849265e758778217dee9134d5b31390e8b2088abce64f6d604bac7e47e4cb15bded86eecccdada99e98341c50238f20b1bfa9578a541b2a43985828131e8fef2340953b58db11364ffc5c1c79ffce4b513b89ce3e9ea7b115d96
};
for (const char *tx_hex: txs_hex)
{
cryptonote::blobdata bd;
ASSERT_TRUE(epee::string_tools::parse_hexstr_to_binbuff(std::string(tx_hex), bd));
cryptonote::transaction tx, pruned_tx;
crypto::hash tx_hash, tx_prefix_hash;
ASSERT_TRUE(parse_and_validate_tx_from_blob(bd, tx, tx_hash, tx_prefix_hash));
ASSERT_TRUE(tx.version == 2);
ASSERT_FALSE(tx.pruned);
ASSERT_TRUE(rct::is_rct_bulletproof(tx.rct_signatures.type));
const uint64_t tx_size = bd.size();
const uint64_t tx_weight = cryptonote::get_transaction_weight(tx);
ASSERT_TRUE(parse_and_validate_tx_base_from_blob(bd, pruned_tx));
ASSERT_TRUE(pruned_tx.version == 2);
ASSERT_TRUE(pruned_tx.pruned);
const uint64_t pruned_tx_weight = cryptonote::get_pruned_transaction_weight(pruned_tx);
ASSERT_EQ(tx_weight, pruned_tx_weight);
}
}