From 66fd49d284b1f8b46b8363c14dd3d8f90cb2e0ac Mon Sep 17 00:00:00 2001 From: Evan Date: Sun, 6 Sep 2026 13:06:03 -0700 Subject: [PATCH 01/17] conditions: ASSERT_MY_ANNEX (0x39) and the annex admission rule The seventh self assert, CONDITIONS.md's ASSERT_MY_ANNEX entry: one 32-byte operand at the generic cost, parsed through the fixed-width rule every 32-byte identity operand shares. The transaction view's BitLisp input gains an optional annex_hash, the BIP341 sha_annex digest of the annex its witness carries, None without one. The assert compares its operand against that field byte-exact, so an input without an annex fails it (unsatisfied_annex_assert). The admission rule of SPEC.md section 3.4: an input carrying an annex hash whose condition list holds no ASSERT_MY_ANNEX is unasserted_annex. It reads the input alone. validate_transaction runs it over every assembled input before any other rule, because a view built without the spend pipeline (every validation vector, the runner's carried inputs) must satisfy the same invariant, and the witness layer will run the same function at its own stage. The runner's tx shape and the compiler's vocabulary mirror gain the field and the name. Invariants: the self assert suite draws the input's own annex hash and annex operands from colliding pools, so environment independence and field equality now cover the assert, and a new property pins that unasserted_annex fires exactly when an annex is present and unasserted. The duplicate suite adds the assert to its idempotent pool. --- python/bitlisp/conditions.py | 20 +++++ python/bitlisp/errors.py | 2 + python/bitlisp/tx.py | 10 ++- python/bitlisp/validation.py | 40 ++++++++- python/bitlisp_tools/cli.py | 6 +- python/bitlisp_tools/compiler.py | 1 + python/bitlisp_tools/runner.py | 18 +++-- python/tests/test_compiler.py | 3 +- python/tests/test_condition_costs.py | 2 + python/tests/test_cost_invariants.py | 5 +- python/tests/test_duplicate_invariants.py | 7 +- python/tests/test_runner.py | 2 + python/tests/test_self_assert_invariants.py | 90 +++++++++++++++++---- python/tests/test_validation_invariants.py | 2 + 14 files changed, 177 insertions(+), 31 deletions(-) diff --git a/python/bitlisp/conditions.py b/python/bitlisp/conditions.py index ad0049e..7e2ce16 100644 --- a/python/bitlisp/conditions.py +++ b/python/bitlisp/conditions.py @@ -53,6 +53,7 @@ ASSERT_MY_SCRIPTPUBKEY = 0x32 ASSERT_MY_AMOUNT = 0x33 ASSERT_MY_TAPTREE = 0x38 +ASSERT_MY_ANNEX = 0x39 ANNOUNCE = 0x40 ASSERT_ANNOUNCEMENT = 0x41 ASSURE = 0x42 @@ -182,6 +183,7 @@ ASSERT_MY_SCRIPTPUBKEY: CONDITION_GENERIC_COST, ASSERT_MY_AMOUNT: CONDITION_GENERIC_COST, ASSERT_MY_TAPTREE: CONDITION_GENERIC_COST, + ASSERT_MY_ANNEX: CONDITION_GENERIC_COST, ANNOUNCE: CONDITION_MESSAGE_COST, ASSERT_ANNOUNCEMENT: CONDITION_MESSAGE_COST, ASSURE: CONDITION_MESSAGE_COST, @@ -317,6 +319,22 @@ class AssertMyTaptree: opcode = ASSERT_MY_TAPTREE +@dataclass(frozen=True) +class AssertMyAnnex: + """Asserts the input's annex by its hash: sha256 over the + compact-size length prefix and the annex element's bytes, the + leading 0x50 included, compared byte-exact against the annex + hash the input's witness carries. An input without an annex + carries no hash, so the assert fails there. The rule that + admits an annex only under this assert runs in validation, not + here: parsing knows one condition at a time. + """ + + annex_hash: bytes + + opcode = ASSERT_MY_ANNEX + + @dataclass(frozen=True) class AssertSig: """Asserts that signature is a valid BIP340 signature by pubkey @@ -843,6 +861,8 @@ def _parse_assigned(opcode, args): return _parse_assert_my_amount(args) if opcode == ASSERT_MY_TAPTREE: return _parse_assert_my_taptree(args) + if opcode == ASSERT_MY_ANNEX: + return _parse_fixed_bytes(args, "ASSERT_MY_ANNEX", AssertMyAnnex, 32) if opcode == ANNOUNCE: return _parse_announce(args) if opcode == ASSERT_ANNOUNCEMENT: diff --git a/python/bitlisp/errors.py b/python/bitlisp/errors.py index 9f9937b..0a2c367 100644 --- a/python/bitlisp/errors.py +++ b/python/bitlisp/errors.py @@ -37,6 +37,8 @@ "unsatisfied_scriptpubkey_assert", "unsatisfied_amount_assert", "unsatisfied_taptree_assert", + "unasserted_annex", + "unsatisfied_annex_assert", "unbalanced_message", "unsatisfied_announcement_assert", "unsatisfied_sig_assert", diff --git a/python/bitlisp/tx.py b/python/bitlisp/tx.py index b984d97..3f90503 100644 --- a/python/bitlisp/tx.py +++ b/python/bitlisp/tx.py @@ -54,7 +54,10 @@ class TxInput: block: tapleaf, the executing leaf's leaf hash, merkle_root, the spending path's root, and internal_key, the x-only key the control block carries. The model takes the triple as - authenticated and never re-derives the scriptPubKey from it.""" + authenticated and never re-derives the scriptPubKey from it. + annex_hash is the BIP341 sha_annex digest of the witness's + annex when it carries one, None otherwise: a hash and never the + bytes, because no rule reads an annex's content.""" txid: bytes index: int @@ -66,6 +69,7 @@ class TxInput: tapleaf: bytes | None = None merkle_root: bytes | None = None internal_key: bytes | None = None + annex_hash: bytes | None = None def __post_init__(self): if not isinstance(self.txid, bytes) or len(self.txid) != 32: @@ -92,6 +96,10 @@ def __post_init__(self): not isinstance(self.internal_key, bytes) or len(self.internal_key) != 32 ): raise ValueError("internal_key must be 32 bytes") + if self.annex_hash is not None and ( + not isinstance(self.annex_hash, bytes) or len(self.annex_hash) != 32 + ): + raise ValueError("annex_hash must be 32 bytes") if self.conditions is not None and ( self.tapleaf is None or self.merkle_root is None diff --git a/python/bitlisp/validation.py b/python/bitlisp/validation.py index 285e994..83784a7 100644 --- a/python/bitlisp/validation.py +++ b/python/bitlisp/validation.py @@ -64,6 +64,7 @@ AssertLocktimeHeight, AssertLocktimeTime, AssertMyAmount, + AssertMyAnnex, AssertMyOutpoint, AssertMyScriptPubKey, AssertMyTaptree, @@ -238,6 +239,38 @@ def check_self_asserts(tx): f"key {tx_input.internal_key.hex()} " f"root {tx_input.merkle_root.hex()}", ) + elif isinstance(cond, AssertMyAnnex): + if cond.annex_hash != tx_input.annex_hash: + raise BitLispError( + "unsatisfied_annex_assert", + f"ASSERT_MY_ANNEX demands {cond.annex_hash.hex()}, the " + "witness carries " + + ( + "no annex" + if tx_input.annex_hash is None + else f"annex hash {tx_input.annex_hash.hex()}" + ), + ) + + +def check_annex_admission(tx_input): + """The annex rule: an input whose witness carries an annex is + valid only when its condition list holds an ASSERT_MY_ANNEX, so + the annex is data the spender committed to and no third party + can attach one. The rule reads the input alone, so the spend + pipeline runs it right after the input's conditions parse, and + validate_transaction runs it again over every assembled input, + because a transaction view built without the pipeline must + satisfy the same invariant. An input without a condition list + is not a BitLisp input and carries no annex the rule reads.""" + if tx_input.annex_hash is None or tx_input.conditions is None: + return + if not any(isinstance(cond, AssertMyAnnex) for cond in tx_input.conditions): + raise BitLispError( + "unasserted_annex", + f"the witness carries an annex hashing to {tx_input.annex_hash.hex()} " + "and the condition list holds no ASSERT_MY_ANNEX", + ) def self_specifier(tx_input, commitment): @@ -420,7 +453,12 @@ def check_seals(tx): def validate_transaction(tx): """Every validation rule that has landed so far, stage 2 work - before stage 4, signature verification last (stage 5).""" + before stage 4, signature verification last (stage 5). The + annex admission rule is per-input work that precedes them all: + a view may have been assembled without the spend pipeline that + already ran it.""" + for tx_input in tx.inputs: + check_annex_admission(tx_input) check_self_asserts(tx) check_output_claims(tx) check_time_asserts(tx) diff --git a/python/bitlisp_tools/cli.py b/python/bitlisp_tools/cli.py index efb918a..701a2bc 100644 --- a/python/bitlisp_tools/cli.py +++ b/python/bitlisp_tools/cli.py @@ -55,7 +55,8 @@ "conditions": "", "tapleaf": "", "merkle_root": "", - "internal_key": ""}], + "internal_key": "", + "annex_hash": ""}], "outputs": [{"script_pubkey": "", "amount": 600}]} --input selects which input the program spends, the first by @@ -64,7 +65,8 @@ merkle_root, and internal_key, the executing input's identity. Any other input carrying a conditions field is a BitLisp input whose evaluation result is taken as given, and the model requires the -same identity triple on it. +same identity triple on it. annex_hash is the sha_annex digest of +the annex an input's witness carries, omitted when it carries none. Exit status 0 when the spend is valid, 1 when it is invalid with the error line pinning the consensus code, 2 for unusable input: a diff --git a/python/bitlisp_tools/compiler.py b/python/bitlisp_tools/compiler.py index 1a67362..6ee608b 100644 --- a/python/bitlisp_tools/compiler.py +++ b/python/bitlisp_tools/compiler.py @@ -149,6 +149,7 @@ "ASSERT_MY_SCRIPTPUBKEY", "ASSERT_MY_AMOUNT", "ASSERT_MY_TAPTREE", + "ASSERT_MY_ANNEX", "ANNOUNCE", "ASSERT_ANNOUNCEMENT", "ASSURE", diff --git a/python/bitlisp_tools/runner.py b/python/bitlisp_tools/runner.py index 45bf5e2..a06e871 100644 --- a/python/bitlisp_tools/runner.py +++ b/python/bitlisp_tools/runner.py @@ -26,6 +26,7 @@ AssertLocktimeHeight, AssertLocktimeTime, AssertMyAmount, + AssertMyAnnex, AssertMyOutpoint, AssertMyScriptPubKey, AssertMyTaptree, @@ -75,12 +76,14 @@ def load_context(obj): The shape is the validation corpus's, closed at every level: version, locktime, inputs, and outputs exactly, each input with txid, index, script_pubkey, and amount plus optional sequence, - conditions, script_sig, tapleaf, merkle_root, and internal_key, - each output with script_pubkey and amount exactly. Byte fields - are plain hex strings. The transaction model requires the - execution-identity triple on every condition-carrying input, and - the runner's target input needs it too, since conditions are - installed there after evaluation. + conditions, script_sig, tapleaf, merkle_root, internal_key, and + annex_hash, each output with script_pubkey and amount exactly. + Byte fields are plain hex strings. The transaction model + requires the execution-identity triple on every + condition-carrying input, and the runner's target input needs + it too, since conditions are installed there after evaluation. + annex_hash is the sha_annex digest of an annex the input's + witness carries, absent when it carries none. A carried conditions field is an already-evaluated serialized condition list. One that does not deserialize is a shape defect, @@ -107,6 +110,7 @@ def load_context(obj): "tapleaf", "merkle_root", "internal_key", + "annex_hash", } decoded_inputs = [] for entry in obj["inputs"]: @@ -153,6 +157,7 @@ def load_context(obj): tapleaf=_optional_hex(entry, "tapleaf"), merkle_root=_optional_hex(entry, "merkle_root"), internal_key=_optional_hex(entry, "internal_key"), + annex_hash=_optional_hex(entry, "annex_hash"), ) for entry, conditions in decoded_inputs ), @@ -221,6 +226,7 @@ def run_spend(program, solution, tx, input_index=0, max_cost=DEFAULT_MAX_COST): AssertMyScriptPubKey: "ASSERT_MY_SCRIPTPUBKEY", AssertMyAmount: "ASSERT_MY_AMOUNT", AssertMyTaptree: "ASSERT_MY_TAPTREE", + AssertMyAnnex: "ASSERT_MY_ANNEX", Announce: "ANNOUNCE", AssertAnnouncement: "ASSERT_ANNOUNCEMENT", Assure: "ASSURE", diff --git a/python/tests/test_compiler.py b/python/tests/test_compiler.py index 8002235..3896e1c 100644 --- a/python/tests/test_compiler.py +++ b/python/tests/test_compiler.py @@ -80,6 +80,7 @@ def _defs(*declarations): (0x32, "ASSERT_MY_SCRIPTPUBKEY"), (0x33, "ASSERT_MY_AMOUNT"), (0x38, "ASSERT_MY_TAPTREE"), + (0x39, "ASSERT_MY_ANNEX"), (0x40, "ANNOUNCE"), (0x41, "ASSERT_ANNOUNCEMENT"), (0x42, "ASSURE"), @@ -91,7 +92,7 @@ def _defs(*declarations): def test_condition_constants_match_spec_table(): - assert len(CONDITION_TABLE_ROWS) == 26 + assert len(CONDITION_TABLE_ROWS) == 27 assert CONDITION_CONSTANTS == { name: int_to_atom(opcode) for opcode, name in CONDITION_TABLE_ROWS } diff --git a/python/tests/test_condition_costs.py b/python/tests/test_condition_costs.py index 7268a94..fae6c3e 100644 --- a/python/tests/test_condition_costs.py +++ b/python/tests/test_condition_costs.py @@ -18,6 +18,7 @@ from bitlisp.conditions import ( # noqa: E402 ANNOUNCE, ASSERT_MY_AMOUNT, + ASSERT_MY_ANNEX, ASSERT_MY_TAPTREE, ASSERT_SIG_RAW, ASSURE, @@ -60,6 +61,7 @@ def test_cost_table_values_match_spec(): assert CONDITION_COSTS[CREATE_OUTPUT] == 1_350_000 assert CONDITION_COSTS[CREATE_OUTPUT_TAPROOT] == 2_650_000 assert CONDITION_COSTS[ASSERT_MY_TAPTREE] == 200 + assert CONDITION_COSTS[ASSERT_MY_ANNEX] == 200 def test_returned_cost_is_the_sum_of_condition_costs(): diff --git a/python/tests/test_cost_invariants.py b/python/tests/test_cost_invariants.py index 1b34c17..c7d6b4c 100644 --- a/python/tests/test_cost_invariants.py +++ b/python/tests/test_cost_invariants.py @@ -42,8 +42,8 @@ def cond(opcode, *args): # One well-formed condition per cost tier, the generic tier drawn -# three times (an amount assert, a time assert, and the identity -# assert), and a reserved declaration off the floor. +# four times (an amount assert, a time assert, the identity assert, +# and the annex assert), and a reserved declaration off the floor. MENU = ( cond(0x33, int_to_atom(1000)), cond(0x20, int_to_atom(800_000)), @@ -52,6 +52,7 @@ def cond(opcode, *args): cond(0x01, b"\x51", int_to_atom(1000)), cond(0x02, GOOD_KEY, b"", int_to_atom(1000)), cond(0x38, GOOD_KEY, b"\x11" * 32), + cond(0x39, b"\x12" * 32), cond(0x80, int_to_atom(600)), ) diff --git a/python/tests/test_duplicate_invariants.py b/python/tests/test_duplicate_invariants.py index 1a2b90e..77c8dd2 100644 --- a/python/tests/test_duplicate_invariants.py +++ b/python/tests/test_duplicate_invariants.py @@ -40,6 +40,7 @@ ) from bitlisp.conditions import ( AssertMyAmount, + AssertMyAnnex, AssertMyOutpoint, AssertMyScriptPubKey, AssertMyTaptree, @@ -64,6 +65,7 @@ AssertMyScriptPubKey, AssertMyAmount, AssertMyTaptree, + AssertMyAnnex, Announce, AssertAnnouncement, Reserved, @@ -89,7 +91,9 @@ def _pool(own_txid, own_script, other_txid, other_script): input's own values with the other input's, so satisfied and failing asserts are both dense, and the taptree asserts pair the identity build_tx installs with a wrong root, so a failing - assert's idempotence stays exercised.""" + assert's idempotence stays exercised. The annex assert always + fails here, the inputs carrying no annex, the one self assert + with no satisfied case in the pool.""" return ( CreateOutput(SCRIPT_A, 1), CreateOutput(SCRIPT_B, 1), @@ -103,6 +107,7 @@ def _pool(own_txid, own_script, other_txid, other_script): AssertMyAmount(1), AssertMyTaptree(FILLER_INTERNAL_KEY, FILLER_MERKLE_ROOT), AssertMyTaptree(FILLER_INTERNAL_KEY, FILLER_TAPLEAF), + AssertMyAnnex(b"\x0d" * 32), AssertLocktimeHeight(600), AssertLocktimeHeight(700), AssertLocktimeTime(500_000_600), diff --git a/python/tests/test_runner.py b/python/tests/test_runner.py index 44d672b..ffb0910 100644 --- a/python/tests/test_runner.py +++ b/python/tests/test_runner.py @@ -27,6 +27,7 @@ AssertLocktimeHeight, AssertLocktimeTime, AssertMyAmount, + AssertMyAnnex, AssertMyOutpoint, AssertMyScriptPubKey, AssertMyTaptree, @@ -115,6 +116,7 @@ def _input(**overrides): AssertMyTaptree(b"\x02" * 32, b"\x04" * 32), "ASSERT_MY_TAPTREE internal_key=0x" + "02" * 32 + " merkle_root=0x" + "04" * 32, ), + (AssertMyAnnex(b"\x07" * 32), "ASSERT_MY_ANNEX annex_hash=0x" + "07" * 32), ( AssertSig(ASSERT_SIG_RAW, b"\x05" * 32, b"", b"\x06" * 64), "ASSERT_SIG_RAW pubkey=0x" + "05" * 32 + " message=0x signature=0x" + "06" * 64, diff --git a/python/tests/test_self_assert_invariants.py b/python/tests/test_self_assert_invariants.py index 87013da..b93d288 100644 --- a/python/tests/test_self_assert_invariants.py +++ b/python/tests/test_self_assert_invariants.py @@ -7,9 +7,10 @@ pin the txid-outpoint subset relation and the taptree assert's indifference to the scriptPubKey plus its agreement, on an honest input, with a plain script assert over the scriptPubKey its -operands derive. Field values -and operands are drawn from small colliding pools so satisfied and -unsatisfied asserts are both dense. +operands derive. The annex assert adds the admission rule: an +input carrying an annex is valid only under the assert. Field +values and operands are drawn from small colliding pools so +satisfied and unsatisfied asserts are both dense. """ from bitlisp import ( @@ -21,6 +22,7 @@ ) from bitlisp.conditions import ( AssertMyAmount, + AssertMyAnnex, AssertMyOutpoint, AssertMyScriptPubKey, AssertMyTaptree, @@ -44,6 +46,10 @@ # The execution identity every transaction carries unless a property # draws one: the shared corpus filler no assert in the pools names. FILLER_IDENTITY = (FILLER_INTERNAL_KEY, FILLER_MERKLE_ROOT) +# Annex hashes, drawn both as the input's own (or None, no annex) and +# as annex assert operands. +ANNEX_A = b"\xa1" * 32 +ANNEX_B = b"\xa2" * 32 # (internal key, merkle root) pairs, drawn both as the input's own # identity and as taptree operands, so the two collide often. @@ -63,6 +69,7 @@ ) amounts = st.sampled_from((0, 1, 50_000, 50_000 + 2**32, 2_100_000_000_000_000)) identities = st.sampled_from(IDENTITIES) +annex_hashes = st.sampled_from((None, ANNEX_A, ANNEX_B)) def _outpoint(txid, index): @@ -75,6 +82,7 @@ def _outpoint(txid, index): scripts.map(AssertMyScriptPubKey), amounts.map(AssertMyAmount), identities.map(lambda t: AssertMyTaptree(*t)), + st.sampled_from((ANNEX_A, ANNEX_B)).map(AssertMyAnnex), ) cond_lists = st.lists(self_asserts, max_size=4) @@ -86,11 +94,14 @@ def _outpoint(txid, index): ) -def build_tx(txid, index, script, amount, conds, env, identity=FILLER_IDENTITY): +def build_tx( + txid, index, script, amount, conds, env, identity=FILLER_IDENTITY, annex=None +): """One BitLisp input carrying only self asserts, an unclaimed zero output, and an environment the family must never read. The unrelated input can sit before the carrying input, so an - implementation reading a fixed input position dies here.""" + implementation reading a fixed input position dies here. annex + is the input's own annex hash, None for a witness without one.""" version, locktime, sequence, extra_position = env internal_key, merkle_root = identity inputs = [ @@ -104,6 +115,7 @@ def build_tx(txid, index, script, amount, conds, env, identity=FILLER_IDENTITY): tapleaf=FILLER_TAPLEAF, merkle_root=merkle_root, internal_key=internal_key, + annex_hash=annex, ) ] if extra_position != "none": @@ -131,17 +143,26 @@ def outcome(tx): @given( - txids, indexes, scripts, amounts, identities, cond_lists, environments, environments + txids, + indexes, + scripts, + amounts, + identities, + annex_hashes, + cond_lists, + environments, + environments, ) def test_outcome_is_environment_independent( - txid, index, script, amount, identity, conds, env_a, env_b + txid, index, script, amount, identity, annex, conds, env_a, env_b ): """The family outcome depends only on the conditions and the - input's own prevout data and identity. Version, locktime, - sequence, and unrelated inputs never change it, the stage 2 - property that makes every self assert recombination-invariant.""" - tx_a = build_tx(txid, index, script, amount, conds, env_a, identity) - tx_b = build_tx(txid, index, script, amount, conds, env_b, identity) + input's own prevout data, identity, and annex. Version, + locktime, sequence, and unrelated inputs never change it, the + stage 2 property that makes every self assert + recombination-invariant.""" + tx_a = build_tx(txid, index, script, amount, conds, env_a, identity, annex) + tx_b = build_tx(txid, index, script, amount, conds, env_b, identity, annex) assert outcome(tx_a) == outcome(tx_b) @@ -159,13 +180,24 @@ def test_satisfied_outpoint_assert_implies_txid_assert( assert outcome(with_txid) is None -@given(txids, indexes, scripts, amounts, identities, self_asserts, environments) +@given( + txids, + indexes, + scripts, + amounts, + identities, + annex_hashes, + self_asserts, + environments, +) def test_single_assert_outcome_matches_field_equality( - txid, index, script, amount, identity, cond, env + txid, index, script, amount, identity, annex, cond, env ): """A lone self assert is satisfied exactly when each operand equals the field it reads, and fails with its field's error - otherwise.""" + otherwise. An input carrying an annex under any other lone + assert fails the admission rule instead, whatever that assert + would have said.""" if isinstance(cond, AssertMyOutpoint): satisfied = cond.outpoint == _outpoint(txid, index) error = "unsatisfied_outpoint_assert" @@ -178,11 +210,35 @@ def test_single_assert_outcome_matches_field_equality( elif isinstance(cond, AssertMyTaptree): satisfied = (cond.internal_key, cond.merkle_root) == identity error = "unsatisfied_taptree_assert" + elif isinstance(cond, AssertMyAnnex): + satisfied = cond.annex_hash == annex + error = "unsatisfied_annex_assert" else: satisfied = cond.amount == amount error = "unsatisfied_amount_assert" - got = outcome(build_tx(txid, index, script, amount, [cond], env, identity)) - assert got == (None if satisfied else error) + got = outcome(build_tx(txid, index, script, amount, [cond], env, identity, annex)) + if annex is not None and not isinstance(cond, AssertMyAnnex): + assert got == "unasserted_annex" + else: + assert got == (None if satisfied else error) + + +@given( + txids, indexes, scripts, amounts, identities, annex_hashes, cond_lists, environments +) +def test_annex_admitted_exactly_under_its_assert( + txid, index, script, amount, identity, annex, conds, env +): + """An input carrying an annex fails as unasserted_annex exactly + when its list holds no ASSERT_MY_ANNEX, before any assert is + checked. Without an annex the admission rule never fires, and + every annex assert in the list is unsatisfied, so the spend is + invalid.""" + got = outcome(build_tx(txid, index, script, amount, conds, env, identity, annex)) + asserted = any(isinstance(cond, AssertMyAnnex) for cond in conds) + assert (got == "unasserted_annex") == (annex is not None and not asserted) + if annex is None and asserted: + assert got is not None @given(txids, indexes, scripts, scripts, amounts, identities, identities, environments) diff --git a/python/tests/test_validation_invariants.py b/python/tests/test_validation_invariants.py index a26d4af..3af87c5 100644 --- a/python/tests/test_validation_invariants.py +++ b/python/tests/test_validation_invariants.py @@ -370,6 +370,8 @@ def test_model_requires_identity_with_conditions(): TxInput(b"\x01" * 32, 0, b"\x51", 1, 0, merkle_root=b"\x0b" * 33) with pytest.raises(ValueError, match="internal_key must be 32 bytes"): TxInput(b"\x01" * 32, 0, b"\x51", 1, 0, internal_key=b"\x0c" * 31) + with pytest.raises(ValueError, match="annex_hash must be 32 bytes"): + TxInput(b"\x01" * 32, 0, b"\x51", 1, 0, annex_hash=b"\x0d" * 33) def test_model_rejects_out_of_range_amounts(): From 5253749dad4a5f5716e7c4a72cf8951c1ac85ba4 Mon Sep 17 00:00:00 2001 From: Evan Date: Sun, 6 Sep 2026 13:06:03 -0700 Subject: [PATCH 02/17] vectors: 0x39 flips from gap to ASSERT_MY_ANNEX gap_0x39_invalid pinned bad_condition_opcode while the vocabulary table of CONDITIONS.md section 2 already assigned 0x39 to ASSERT_MY_ANNEX (spec commit d50da1e, condition-record decision 30). The vector was wrong against the spec from that commit and stayed so on purpose until the implementation landed. It is replaced by the assert's parse case and its rejections: 31 and 33 byte operands, an empty operand, a pair operand, arity zero and two. costs.json gains the assert's 200 line, its exact-budget pair, and the annex condition in the all-opcodes sum, whose total rises by 200 to 14,405,400 (COSTS.md section 10, one generic entry more). validation/self-asserts.json pins the assert and the admission rule of SPEC.md section 3.4 in both directions: satisfied, wrong hash, assert without an annex, annex without the assert (with an empty list, with a satisfied assert, and with a failing assert the admission rule precedes), an annex asserted then a later assert failing on its own error, duplicate and contradictory annex asserts, and an annex hash on a plain input, which no rule reads. The annex every case hashes is 0x50 then the ASCII bytes "annex". --- tools/run_vectors.py | 8 +- vectors/README.md | 11 +- vectors/conditions/costs.json | 49 ++++- vectors/conditions/self-asserts.json | 61 +++++- vectors/validation/self-asserts.json | 295 +++++++++++++++++++++++++++ 5 files changed, 406 insertions(+), 18 deletions(-) diff --git a/tools/run_vectors.py b/tools/run_vectors.py index 68ab295..cb0421a 100755 --- a/tools/run_vectors.py +++ b/tools/run_vectors.py @@ -203,7 +203,7 @@ def run_conditions_case(case): entry's name ("outpoint", "txid", "script_pubkey", "amount"), amounts as integers, bytes as hex. ASSERT_MY_TAPTREE pins {"opcode", "internal_key", "merkle_root"}, its two operands and - nothing derived. + nothing derived. ASSERT_MY_ANNEX pins {"opcode", "annex_hash"}. The message family pins specifiers as {"commitment", "fields"} with fields in operand order, amounts as integers, all other @@ -271,7 +271,8 @@ def run_validation_case(case): "conditions": "", "tapleaf": "<32-byte hex, required with conditions>", "merkle_root": "<32-byte hex, required with conditions>", - "internal_key": "<32-byte hex, required with conditions>"}], + "internal_key": "<32-byte hex, required with conditions>", + "annex_hash": "<32-byte hex, optional>"}], "outputs": [{"script_pubkey": "", "amount": }] }, "expect": {"valid": true} or {"error": ""} @@ -279,7 +280,8 @@ def run_validation_case(case): An input without a conditions key is a non-BitLisp input. An input with one is a BitLisp input whose program evaluation - produced that condition list. + produced that condition list. annex_hash is the sha_annex digest + of the annex the input's witness carries, absent without one. """ from bitlisp import BitLispError, validate_transaction from bitlisp.errors import CODES diff --git a/vectors/README.md b/vectors/README.md index b35108e..8dd9158 100644 --- a/vectors/README.md +++ b/vectors/README.md @@ -72,7 +72,8 @@ condition (`{"opcode", "script_pubkey", "amount"}` for CREATE_OUTPUT, `{"opcode", "internal_key", "merkle_root", "amount", "script_pubkey"}` for CREATE_OUTPUT_TAPROOT with `script_pubkey` the derived taproot script, `{"opcode", "internal_key", "merkle_root"}` for -ASSERT_MY_TAPTREE, `{"opcode"}` plus the operand under its entry's argument name +ASSERT_MY_TAPTREE, `{"opcode", "annex_hash"}` for ASSERT_MY_ANNEX, +`{"opcode"}` plus the operand under its entry's argument name (`"height"`, `"time"`, `"blocks"`, `"units"`) for the time asserts, `{"opcode", "cost", "args": [""]}` for reserved conditions) or `{"error": ""}`. The message family pins @@ -103,7 +104,8 @@ CONDITIONS.md section 1 and VALIDATION.md rule 6 has at least one case. "conditions": "", "tapleaf": "", "merkle_root": "", - "internal_key": "" + "internal_key": "", + "annex_hash": "" } ], "outputs": [{"script_pubkey": "", "amount": 50000}] @@ -123,7 +125,10 @@ each exactly 32 bytes: the triple base consensus authenticates from the control block. Rule 3's composed specifiers read the first two, ASSERT_MY_TAPTREE reads the last two. The model rejects a condition-carrying input without all three, and derives nothing -from them, so a family-suite input may carry filler. `expect` +from them, so a family-suite input may carry filler. `annex_hash` +is the BIP341 `sha_annex` digest of the annex the input's witness +carries, present exactly when it carries one: ASSERT_MY_ANNEX reads +it, and an input carrying one without the assert is invalid. `expect` is `{"valid": true}` or `{"error": ""}`. The transaction must satisfy the model's base rules (value conservation, ranges, distinct outpoints): a case violating them is a malformed vector, not an diff --git a/vectors/conditions/costs.json b/vectors/conditions/costs.json index b73d6fc..b203537 100644 --- a/vectors/conditions/costs.json +++ b/vectors/conditions/costs.json @@ -121,6 +121,19 @@ "cost": 200 } }, + { + "name": "generic_annex_assert_costs_200", + "conditions": "ffff39ffa09ead2a42d43638f5cd0d2f61f94c8786211ea1d678445db915507c61bbcbf07c8080", + "expect": { + "parsed": [ + { + "opcode": 57, + "annex_hash": "9ead2a42d43638f5cd0d2f61f94c8786211ea1d678445db915507c61bbcbf07c" + } + ], + "cost": 200 + } + }, { "name": "generic_reserve_fee_costs_200", "conditions": "ffff50ff8203e88080", @@ -380,8 +393,8 @@ }, { "name": "all_assigned_opcodes_total", - "conditions": "ffff01ff51ff8203e880ffff02ffa079be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798ff80ff8203e880ffff10ffa00202020202020202020202020202020202020202020202020202020202020202ff836d7367ffc0400303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030380ffff11ffa00202020202020202020202020202020202020202020202020202020202020202ff836d7367ffc0400303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030380ffff12ffa00202020202020202020202020202020202020202020202020202020202020202ff836d7367ffc0400303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030380ffff13ffa00202020202020202020202020202020202020202020202020202020202020202ff836d7367ffc0400303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030380ffff14ffa00202020202020202020202020202020202020202020202020202020202020202ff836d7367ffc0400303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030380ffff15ffa00202020202020202020202020202020202020202020202020202020202020202ff836d7367ffc0400303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030380ffff16ffa00202020202020202020202020202020202020202020202020202020202020202ff836d7367ffc0400303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030380ffff17ffa00202020202020202020202020202020202020202020202020202020202020202ff836d7367ffc0400303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030380ffff20ff830c350080ffff21ff8423c3460080ffff22ff0a80ffff23ff0a80ffff30ffa400000000000000000000000000000000000000000000000000000000000000000000000080ffff31ffa0111111111111111111111111111111111111111111111111111111111111111180ffff32ff5180ffff33ff8203e880ffff38ffa079be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798ffa0111111111111111111111111111111111111111111111111111111111111111180ffff40ff826e73ff877061796c6f616480ffff41ff80ff826e73ff877061796c6f616480ffff42ff80ff836d736780ffff43ff80ff836d736780ffff50ff8203e880ffff60ffa0111111111111111111111111111111111111111111111111111111111111111180ffff61ffa011111111111111111111111111111111111111111111111111111111111111118080", - "max_cost": 14405200, + "conditions": "ffff01ff51ff8203e880ffff02ffa079be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798ff80ff8203e880ffff10ffa00202020202020202020202020202020202020202020202020202020202020202ff836d7367ffc0400303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030380ffff11ffa00202020202020202020202020202020202020202020202020202020202020202ff836d7367ffc0400303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030380ffff12ffa00202020202020202020202020202020202020202020202020202020202020202ff836d7367ffc0400303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030380ffff13ffa00202020202020202020202020202020202020202020202020202020202020202ff836d7367ffc0400303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030380ffff14ffa00202020202020202020202020202020202020202020202020202020202020202ff836d7367ffc0400303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030380ffff15ffa00202020202020202020202020202020202020202020202020202020202020202ff836d7367ffc0400303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030380ffff16ffa00202020202020202020202020202020202020202020202020202020202020202ff836d7367ffc0400303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030380ffff17ffa00202020202020202020202020202020202020202020202020202020202020202ff836d7367ffc0400303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030380ffff20ff830c350080ffff21ff8423c3460080ffff22ff0a80ffff23ff0a80ffff30ffa400000000000000000000000000000000000000000000000000000000000000000000000080ffff31ffa0111111111111111111111111111111111111111111111111111111111111111180ffff32ff5180ffff33ff8203e880ffff38ffa079be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798ffa0111111111111111111111111111111111111111111111111111111111111111180ffff39ffa0111111111111111111111111111111111111111111111111111111111111111180ffff40ff826e73ff877061796c6f616480ffff41ff80ff826e73ff877061796c6f616480ffff42ff80ff836d736780ffff43ff80ff836d736780ffff50ff8203e880ffff60ffa0111111111111111111111111111111111111111111111111111111111111111180ffff61ffa011111111111111111111111111111111111111111111111111111111111111118080", + "max_cost": 14405400, "expect": { "parsed": [ { @@ -481,6 +494,10 @@ "internal_key": "79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798", "merkle_root": "1111111111111111111111111111111111111111111111111111111111111111" }, + { + "opcode": 57, + "annex_hash": "1111111111111111111111111111111111111111111111111111111111111111" + }, { "opcode": 64, "namespace": "6e73", @@ -526,13 +543,13 @@ "outputs_hash": "1111111111111111111111111111111111111111111111111111111111111111" } ], - "cost": 14405200 + "cost": 14405400 } }, { "name": "all_assigned_opcodes_one_below_bursts", - "conditions": "ffff01ff51ff8203e880ffff02ffa079be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798ff80ff8203e880ffff10ffa00202020202020202020202020202020202020202020202020202020202020202ff836d7367ffc0400303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030380ffff11ffa00202020202020202020202020202020202020202020202020202020202020202ff836d7367ffc0400303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030380ffff12ffa00202020202020202020202020202020202020202020202020202020202020202ff836d7367ffc0400303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030380ffff13ffa00202020202020202020202020202020202020202020202020202020202020202ff836d7367ffc0400303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030380ffff14ffa00202020202020202020202020202020202020202020202020202020202020202ff836d7367ffc0400303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030380ffff15ffa00202020202020202020202020202020202020202020202020202020202020202ff836d7367ffc0400303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030380ffff16ffa00202020202020202020202020202020202020202020202020202020202020202ff836d7367ffc0400303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030380ffff17ffa00202020202020202020202020202020202020202020202020202020202020202ff836d7367ffc0400303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030380ffff20ff830c350080ffff21ff8423c3460080ffff22ff0a80ffff23ff0a80ffff30ffa400000000000000000000000000000000000000000000000000000000000000000000000080ffff31ffa0111111111111111111111111111111111111111111111111111111111111111180ffff32ff5180ffff33ff8203e880ffff38ffa079be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798ffa0111111111111111111111111111111111111111111111111111111111111111180ffff40ff826e73ff877061796c6f616480ffff41ff80ff826e73ff877061796c6f616480ffff42ff80ff836d736780ffff43ff80ff836d736780ffff50ff8203e880ffff60ffa0111111111111111111111111111111111111111111111111111111111111111180ffff61ffa011111111111111111111111111111111111111111111111111111111111111118080", - "max_cost": 14405199, + "conditions": "ffff01ff51ff8203e880ffff02ffa079be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798ff80ff8203e880ffff10ffa00202020202020202020202020202020202020202020202020202020202020202ff836d7367ffc0400303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030380ffff11ffa00202020202020202020202020202020202020202020202020202020202020202ff836d7367ffc0400303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030380ffff12ffa00202020202020202020202020202020202020202020202020202020202020202ff836d7367ffc0400303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030380ffff13ffa00202020202020202020202020202020202020202020202020202020202020202ff836d7367ffc0400303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030380ffff14ffa00202020202020202020202020202020202020202020202020202020202020202ff836d7367ffc0400303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030380ffff15ffa00202020202020202020202020202020202020202020202020202020202020202ff836d7367ffc0400303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030380ffff16ffa00202020202020202020202020202020202020202020202020202020202020202ff836d7367ffc0400303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030380ffff17ffa00202020202020202020202020202020202020202020202020202020202020202ff836d7367ffc0400303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030380ffff20ff830c350080ffff21ff8423c3460080ffff22ff0a80ffff23ff0a80ffff30ffa400000000000000000000000000000000000000000000000000000000000000000000000080ffff31ffa0111111111111111111111111111111111111111111111111111111111111111180ffff32ff5180ffff33ff8203e880ffff38ffa079be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798ffa0111111111111111111111111111111111111111111111111111111111111111180ffff39ffa0111111111111111111111111111111111111111111111111111111111111111180ffff40ff826e73ff877061796c6f616480ffff41ff80ff826e73ff877061796c6f616480ffff42ff80ff836d736780ffff43ff80ff836d736780ffff50ff8203e880ffff60ffa0111111111111111111111111111111111111111111111111111111111111111180ffff61ffa011111111111111111111111111111111111111111111111111111111111111118080", + "max_cost": 14405399, "expect": { "error": "cost_exceeded" } @@ -677,6 +694,28 @@ "error": "cost_exceeded" } }, + { + "name": "assert_my_annex_exact_budget_passes", + "conditions": "ffff39ffa09ead2a42d43638f5cd0d2f61f94c8786211ea1d678445db915507c61bbcbf07c8080", + "max_cost": 200, + "expect": { + "parsed": [ + { + "opcode": 57, + "annex_hash": "9ead2a42d43638f5cd0d2f61f94c8786211ea1d678445db915507c61bbcbf07c" + } + ], + "cost": 200 + } + }, + { + "name": "assert_my_annex_one_below_bursts", + "conditions": "ffff39ffa09ead2a42d43638f5cd0d2f61f94c8786211ea1d678445db915507c61bbcbf07c8080", + "max_cost": 199, + "expect": { + "error": "cost_exceeded" + } + }, { "name": "empty_list_satisfies_zero_budget", "conditions": "80", diff --git a/vectors/conditions/self-asserts.json b/vectors/conditions/self-asserts.json index 2b4d55c..f07f0bf 100644 --- a/vectors/conditions/self-asserts.json +++ b/vectors/conditions/self-asserts.json @@ -265,6 +265,60 @@ "error": "bad_condition_arg" } }, + { + "name": "annex_parses", + "conditions": "ffff39ffa09ead2a42d43638f5cd0d2f61f94c8786211ea1d678445db915507c61bbcbf07c8080", + "expect": { + "parsed": [ + { + "opcode": 57, + "annex_hash": "9ead2a42d43638f5cd0d2f61f94c8786211ea1d678445db915507c61bbcbf07c" + } + ] + } + }, + { + "name": "annex_31_bytes", + "conditions": "ffff39ff9f9ead2a42d43638f5cd0d2f61f94c8786211ea1d678445db915507c61bbcbf08080", + "expect": { + "error": "bad_condition_arg" + } + }, + { + "name": "annex_33_bytes", + "conditions": "ffff39ffa19ead2a42d43638f5cd0d2f61f94c8786211ea1d678445db915507c61bbcbf07c008080", + "expect": { + "error": "bad_condition_arg" + } + }, + { + "name": "annex_empty", + "conditions": "ffff39ff808080", + "expect": { + "error": "bad_condition_arg" + } + }, + { + "name": "annex_arity_zero", + "conditions": "ffff398080", + "expect": { + "error": "bad_condition_arity" + } + }, + { + "name": "annex_arity_two", + "conditions": "ffff39ffa09ead2a42d43638f5cd0d2f61f94c8786211ea1d678445db915507c61bbcbf07cffa09ead2a42d43638f5cd0d2f61f94c8786211ea1d678445db915507c61bbcbf07c8080", + "expect": { + "error": "bad_condition_arity" + } + }, + { + "name": "annex_operand_is_pair", + "conditions": "ffff39ffffa09ead2a42d43638f5cd0d2f61f94c8786211ea1d678445db915507c61bbcbf07c808080", + "expect": { + "error": "bad_condition_arg" + } + }, { "name": "txid_operand_not_atom", "conditions": "ffff31ffffa01111111111111111111111111111111111111111111111111111111111111111808080", @@ -314,13 +368,6 @@ "error": "bad_condition_opcode" } }, - { - "name": "gap_0x39_invalid", - "conditions": "ffff39ffa011111111111111111111111111111111111111111111111111111111111111118080", - "expect": { - "error": "bad_condition_opcode" - } - }, { "name": "scriptpubkey_arity_zero", "conditions": "ffff328080", diff --git a/vectors/validation/self-asserts.json b/vectors/validation/self-asserts.json index b1d9c57..2571049 100644 --- a/vectors/validation/self-asserts.json +++ b/vectors/validation/self-asserts.json @@ -1056,6 +1056,301 @@ "expect": { "valid": true } + }, + { + "name": "annex_satisfied", + "tx": { + "version": 2, + "locktime": 0, + "inputs": [ + { + "txid": "1111111111111111111111111111111111111111111111111111111111111111", + "index": 1, + "script_pubkey": "5120147c9c57132f6e7ecddba9800bb0c4449251c92a1e60371ee77557b6620f3ea3", + "amount": 50000, + "conditions": "ffff39ffa09ead2a42d43638f5cd0d2f61f94c8786211ea1d678445db915507c61bbcbf07c8080", + "tapleaf": "0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a", + "merkle_root": "5b75adecf53548f3ec6ad7d78383bf84cc57b55a3127c72b9a2481752dd88b21", + "internal_key": "187791b6f712a8ea41c8ecdd0ee77fab3e85263b37e1ec18a3651926b3a6cf27", + "annex_hash": "9ead2a42d43638f5cd0d2f61f94c8786211ea1d678445db915507c61bbcbf07c" + } + ], + "outputs": [ + { + "script_pubkey": "0014bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", + "amount": 40000 + } + ] + }, + "expect": { + "valid": true + } + }, + { + "name": "annex_wrong_hash", + "tx": { + "version": 2, + "locktime": 0, + "inputs": [ + { + "txid": "1111111111111111111111111111111111111111111111111111111111111111", + "index": 1, + "script_pubkey": "5120147c9c57132f6e7ecddba9800bb0c4449251c92a1e60371ee77557b6620f3ea3", + "amount": 50000, + "conditions": "ffff39ffa011111111111111111111111111111111111111111111111111111111111111118080", + "tapleaf": "0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a", + "merkle_root": "5b75adecf53548f3ec6ad7d78383bf84cc57b55a3127c72b9a2481752dd88b21", + "internal_key": "187791b6f712a8ea41c8ecdd0ee77fab3e85263b37e1ec18a3651926b3a6cf27", + "annex_hash": "9ead2a42d43638f5cd0d2f61f94c8786211ea1d678445db915507c61bbcbf07c" + } + ], + "outputs": [ + { + "script_pubkey": "0014bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", + "amount": 40000 + } + ] + }, + "expect": { + "error": "unsatisfied_annex_assert" + } + }, + { + "name": "annex_assert_without_annex", + "tx": { + "version": 2, + "locktime": 0, + "inputs": [ + { + "txid": "1111111111111111111111111111111111111111111111111111111111111111", + "index": 1, + "script_pubkey": "5120147c9c57132f6e7ecddba9800bb0c4449251c92a1e60371ee77557b6620f3ea3", + "amount": 50000, + "conditions": "ffff39ffa09ead2a42d43638f5cd0d2f61f94c8786211ea1d678445db915507c61bbcbf07c8080", + "tapleaf": "0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a", + "merkle_root": "5b75adecf53548f3ec6ad7d78383bf84cc57b55a3127c72b9a2481752dd88b21", + "internal_key": "187791b6f712a8ea41c8ecdd0ee77fab3e85263b37e1ec18a3651926b3a6cf27" + } + ], + "outputs": [ + { + "script_pubkey": "0014bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", + "amount": 40000 + } + ] + }, + "expect": { + "error": "unsatisfied_annex_assert" + } + }, + { + "name": "annex_unasserted", + "tx": { + "version": 2, + "locktime": 0, + "inputs": [ + { + "txid": "1111111111111111111111111111111111111111111111111111111111111111", + "index": 1, + "script_pubkey": "5120147c9c57132f6e7ecddba9800bb0c4449251c92a1e60371ee77557b6620f3ea3", + "amount": 50000, + "conditions": "ffff33ff8300c3508080", + "tapleaf": "0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a", + "merkle_root": "5b75adecf53548f3ec6ad7d78383bf84cc57b55a3127c72b9a2481752dd88b21", + "internal_key": "187791b6f712a8ea41c8ecdd0ee77fab3e85263b37e1ec18a3651926b3a6cf27", + "annex_hash": "9ead2a42d43638f5cd0d2f61f94c8786211ea1d678445db915507c61bbcbf07c" + } + ], + "outputs": [ + { + "script_pubkey": "0014bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", + "amount": 40000 + } + ] + }, + "expect": { + "error": "unasserted_annex" + } + }, + { + "name": "annex_unasserted_empty_list", + "tx": { + "version": 2, + "locktime": 0, + "inputs": [ + { + "txid": "1111111111111111111111111111111111111111111111111111111111111111", + "index": 1, + "script_pubkey": "5120147c9c57132f6e7ecddba9800bb0c4449251c92a1e60371ee77557b6620f3ea3", + "amount": 50000, + "conditions": "80", + "tapleaf": "0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a", + "merkle_root": "5b75adecf53548f3ec6ad7d78383bf84cc57b55a3127c72b9a2481752dd88b21", + "internal_key": "187791b6f712a8ea41c8ecdd0ee77fab3e85263b37e1ec18a3651926b3a6cf27", + "annex_hash": "9ead2a42d43638f5cd0d2f61f94c8786211ea1d678445db915507c61bbcbf07c" + } + ], + "outputs": [ + { + "script_pubkey": "0014bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", + "amount": 40000 + } + ] + }, + "expect": { + "error": "unasserted_annex" + } + }, + { + "name": "annex_unasserted_precedes_failing_assert", + "tx": { + "version": 2, + "locktime": 0, + "inputs": [ + { + "txid": "1111111111111111111111111111111111111111111111111111111111111111", + "index": 1, + "script_pubkey": "5120147c9c57132f6e7ecddba9800bb0c4449251c92a1e60371ee77557b6620f3ea3", + "amount": 50000, + "conditions": "ffff33ff018080", + "tapleaf": "0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a", + "merkle_root": "5b75adecf53548f3ec6ad7d78383bf84cc57b55a3127c72b9a2481752dd88b21", + "internal_key": "187791b6f712a8ea41c8ecdd0ee77fab3e85263b37e1ec18a3651926b3a6cf27", + "annex_hash": "9ead2a42d43638f5cd0d2f61f94c8786211ea1d678445db915507c61bbcbf07c" + } + ], + "outputs": [ + { + "script_pubkey": "0014bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", + "amount": 40000 + } + ] + }, + "expect": { + "error": "unasserted_annex" + } + }, + { + "name": "annex_asserted_then_failing_assert", + "tx": { + "version": 2, + "locktime": 0, + "inputs": [ + { + "txid": "1111111111111111111111111111111111111111111111111111111111111111", + "index": 1, + "script_pubkey": "5120147c9c57132f6e7ecddba9800bb0c4449251c92a1e60371ee77557b6620f3ea3", + "amount": 50000, + "conditions": "ffff39ffa09ead2a42d43638f5cd0d2f61f94c8786211ea1d678445db915507c61bbcbf07c80ffff33ff018080", + "tapleaf": "0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a", + "merkle_root": "5b75adecf53548f3ec6ad7d78383bf84cc57b55a3127c72b9a2481752dd88b21", + "internal_key": "187791b6f712a8ea41c8ecdd0ee77fab3e85263b37e1ec18a3651926b3a6cf27", + "annex_hash": "9ead2a42d43638f5cd0d2f61f94c8786211ea1d678445db915507c61bbcbf07c" + } + ], + "outputs": [ + { + "script_pubkey": "0014bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", + "amount": 40000 + } + ] + }, + "expect": { + "error": "unsatisfied_amount_assert" + } + }, + { + "name": "annex_duplicate_idempotent", + "tx": { + "version": 2, + "locktime": 0, + "inputs": [ + { + "txid": "1111111111111111111111111111111111111111111111111111111111111111", + "index": 1, + "script_pubkey": "5120147c9c57132f6e7ecddba9800bb0c4449251c92a1e60371ee77557b6620f3ea3", + "amount": 50000, + "conditions": "ffff39ffa09ead2a42d43638f5cd0d2f61f94c8786211ea1d678445db915507c61bbcbf07c80ffff39ffa09ead2a42d43638f5cd0d2f61f94c8786211ea1d678445db915507c61bbcbf07c8080", + "tapleaf": "0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a", + "merkle_root": "5b75adecf53548f3ec6ad7d78383bf84cc57b55a3127c72b9a2481752dd88b21", + "internal_key": "187791b6f712a8ea41c8ecdd0ee77fab3e85263b37e1ec18a3651926b3a6cf27", + "annex_hash": "9ead2a42d43638f5cd0d2f61f94c8786211ea1d678445db915507c61bbcbf07c" + } + ], + "outputs": [ + { + "script_pubkey": "0014bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", + "amount": 40000 + } + ] + }, + "expect": { + "valid": true + } + }, + { + "name": "annex_contradictory_asserts", + "tx": { + "version": 2, + "locktime": 0, + "inputs": [ + { + "txid": "1111111111111111111111111111111111111111111111111111111111111111", + "index": 1, + "script_pubkey": "5120147c9c57132f6e7ecddba9800bb0c4449251c92a1e60371ee77557b6620f3ea3", + "amount": 50000, + "conditions": "ffff39ffa09ead2a42d43638f5cd0d2f61f94c8786211ea1d678445db915507c61bbcbf07c80ffff39ffa011111111111111111111111111111111111111111111111111111111111111118080", + "tapleaf": "0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a", + "merkle_root": "5b75adecf53548f3ec6ad7d78383bf84cc57b55a3127c72b9a2481752dd88b21", + "internal_key": "187791b6f712a8ea41c8ecdd0ee77fab3e85263b37e1ec18a3651926b3a6cf27", + "annex_hash": "9ead2a42d43638f5cd0d2f61f94c8786211ea1d678445db915507c61bbcbf07c" + } + ], + "outputs": [ + { + "script_pubkey": "0014bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", + "amount": 40000 + } + ] + }, + "expect": { + "error": "unsatisfied_annex_assert" + } + }, + { + "name": "annex_on_plain_input_unread", + "tx": { + "version": 2, + "locktime": 0, + "inputs": [ + { + "txid": "1111111111111111111111111111111111111111111111111111111111111111", + "index": 1, + "script_pubkey": "5120147c9c57132f6e7ecddba9800bb0c4449251c92a1e60371ee77557b6620f3ea3", + "amount": 50000, + "conditions": "ffff33ff8300c3508080", + "tapleaf": "0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a", + "merkle_root": "5b75adecf53548f3ec6ad7d78383bf84cc57b55a3127c72b9a2481752dd88b21", + "internal_key": "187791b6f712a8ea41c8ecdd0ee77fab3e85263b37e1ec18a3651926b3a6cf27" + }, + { + "txid": "2222222222222222222222222222222222222222222222222222222222222222", + "index": 0, + "script_pubkey": "0014cccccccccccccccccccccccccccccccccccccccc", + "amount": 1, + "annex_hash": "9ead2a42d43638f5cd0d2f61f94c8786211ea1d678445db915507c61bbcbf07c" + } + ], + "outputs": [ + { + "script_pubkey": "0014bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", + "amount": 40000 + } + ] + }, + "expect": { + "valid": true + } } ] } From f45459851364cb09b1e29502a3bc6859dac7272b Mon Sep 17 00:00:00 2001 From: Evan Date: Sun, 6 Sep 2026 13:11:37 -0700 Subject: [PATCH 03/17] spec: the nil program is spendable by anyone Section 3.3 said the nil program's empty condition list is rejected as bad_condition_list and the nil leaf has no valid spend. It contradicted CONDITIONS.md section 1, under which the empty list is a proper list and parses to no conditions, VALIDATION.md rule 5, which says the empty list charges nothing and satisfies any budget, and the corpus, where conditions/costs.json pins the empty list as valid and three validation files carry a valid input whose list is empty. Chialisp agrees: a coin spend producing no conditions is valid. The section now states what the rules give: the nil leaf is spendable by anyone, its spend contributing no condition. The two named programs differ in who chooses the conditions, the spender under the atom 1 and nobody under nil. Found while writing the witness layer's vector for the nil program. --- spec/SPEC.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/spec/SPEC.md b/spec/SPEC.md index 52c3777..18a6f40 100644 --- a/spec/SPEC.md +++ b/spec/SPEC.md @@ -254,10 +254,11 @@ VALIDATION.md's rules run over the assembled transaction. Two programs follow from these rules and are named so they are pinned. The program that is the atom `1` returns its solution, so a leaf committing to it accepts any condition list the spender -supplies: the anyone-can-spend leaf. The program nil returns nil, -the empty list, which CONDITIONS.md rejects as -`bad_condition_list`, so a leaf committing to nil has no valid -script-path spend. +supplies: the anyone-can-spend leaf. The program nil returns nil +whatever the solution, the empty condition list, which +CONDITIONS.md accepts and which constrains nothing, so a leaf +committing to nil is spendable by anyone too, its spend +contributing no condition to the transaction. ### 3.4 The annex From 4ca2488d89b41b04e728f1976316034626c69699 Mon Sep 17 00:00:00 2001 From: Evan Date: Sun, 6 Sep 2026 13:11:37 -0700 Subject: [PATCH 04/17] spend: the witness layer, SPEC.md sections 2 to 4 Two consensus modules. commitment.py is the hashing of section 2: the tree hash over a node (moved here from the compiler, which now imports it, since the leaf script is consensus data), BIP340's tagged hash, the TapLeaf hash under a leaf version, the TapBranch fold of a control block's path, the annex digest, and a control block parsed into leaf version, parity, internal key, and path. spend.py is sections 3 and 4: evaluate_spend takes the input as the transaction carries it before evaluation, the witness elements in serialization order, and the budget, and returns the accrued cost with the input carrying its condition list, execution identity, and annex hash. The stages run in the spec's order. The annex is set aside by the BIP341 rule (two or more elements, the last beginning 0x50), then base consensus's own checks run as a precondition: two or more elements, a control block of 33 plus 32m bytes with m at most 128, BitLisp's leaf version, and the internal key tweaked by the revealed leaf's root giving the spent scriptPubKey with the parity bit matching. Those checks precede stage 1 in the spec and a spend failing them never reaches it, so they raise BaseConsensusError, a class outside the error taxonomy, never a code a vector could pin as BitLisp behavior. secp256k1 gains taproot_output_point, the full point, so the parity bit can be read. Stage 1 is widths: four elements, a 32-byte leaf script, the solution, program, and annex each at most MAX_WITNESS_ELEMENT_SIZE = 10,000 bytes, bad_witness. Stage 2 decodes the program and compares its tree hash to the leaf script, leaf_mismatch. Stage 3 decodes the solution. Stage 4 is run, stage 5 parse_conditions on the same budget and then the annex admission rule, the same function validate_transaction runs. The two new codes join CODES beside bad_encoding. Every element decodes under the strict deserializer, so an element with trailing bytes is bad_encoding at its stage, the surplus tolerance being inside the solution node, not around it. --- python/bitlisp/__init__.py | 9 +- python/bitlisp/commitment.py | 170 +++++++++++++++++++++++++++++++ python/bitlisp/errors.py | 16 +++ python/bitlisp/secp256k1.py | 30 ++++-- python/bitlisp/spend.py | 148 +++++++++++++++++++++++++++ python/bitlisp_tools/compiler.py | 23 +---- 6 files changed, 366 insertions(+), 30 deletions(-) create mode 100644 python/bitlisp/commitment.py create mode 100644 python/bitlisp/spend.py diff --git a/python/bitlisp/__init__.py b/python/bitlisp/__init__.py index e2a5e9c..f4b2153 100644 --- a/python/bitlisp/__init__.py +++ b/python/bitlisp/__init__.py @@ -6,6 +6,7 @@ and by property-based invariants where none does. """ +from .commitment import BITLISP_LEAF_VERSION, tree_hash from .conditions import ( MAX_MONEY, Announce, @@ -23,10 +24,11 @@ condition_cost, parse_conditions, ) -from .errors import CODES, BitLispError +from .errors import CODES, BaseConsensusError, BitLispError from .machine import run, run_serialized from .serialize import deserialize, serialize from .sexp import NIL, TRUE, atom_to_int, int_to_atom, is_atom, is_pair +from .spend import MAX_WITNESS_ELEMENT_SIZE, evaluate_spend from .tx import Transaction, TxInput, TxOutput from .validation import validate_transaction @@ -39,12 +41,15 @@ "AssertLocktimeTime", "AssertSequenceHeight", "AssertSequenceTime", + "BITLISP_LEAF_VERSION", + "BaseConsensusError", "BitLispError", "CODES", "CreateOutput", "CreateOutputTaproot", "Specifier", "MAX_MONEY", + "MAX_WITNESS_ELEMENT_SIZE", "NIL", "Require", "Reserved", @@ -56,6 +61,7 @@ "atom_to_int", "condition_cost", "deserialize", + "evaluate_spend", "int_to_atom", "is_atom", "is_pair", @@ -63,5 +69,6 @@ "run", "run_serialized", "serialize", + "tree_hash", "validate_transaction", ] diff --git a/python/bitlisp/commitment.py b/python/bitlisp/commitment.py new file mode 100644 index 0000000..8d92feb --- /dev/null +++ b/python/bitlisp/commitment.py @@ -0,0 +1,170 @@ +"""The commitment scheme: how an output commits to a program and how +a spend's control block names the tree it executes in. + +A program is committed as one leaf of a BIP341 script tree under +BitLisp's leaf version. The leaf script is the program's 32-byte tree +hash, never executed, and the program itself travels in the witness +to be checked against it. Everything here is hashing: the tree hash +over a node, BIP341's tagged hashes over the leaf, the branch fold, +and the annex digest. Point arithmetic stays in secp256k1. +""" + +import hashlib +from dataclasses import dataclass + +from . import secp256k1 +from .errors import BaseConsensusError +from .sexp import is_pair + +# PROVISIONAL: fixed at deployment. Any compliant byte works, the low +# bit clear, and nothing else in the scheme depends on which one. +BITLISP_LEAF_VERSION = 0xD0 + +# BIP341's control block: one leaf-version-and-parity byte, the 32-byte +# x-only internal key, then 32 bytes per merkle path element, at most +# 128 of them. +CONTROL_BLOCK_BASE_SIZE = 33 +MERKLE_PATH_MAX_DEPTH = 128 +LEAF_VERSION_MASK = 0xFE + +# The first byte of a BIP341 annex. +ANNEX_TAG = 0x50 + + +def tree_hash(node): + """The tree hash of a node, the value sha256tree computes: an atom + hashes as SHA-256 of 0x01 then its bytes, a pair as SHA-256 of + 0x02 then the first child's hash then the rest child's hash. An + explicit stack, so a deep program never meets the recursion + limit. Uncharged: the caller prices the bytes that carried the + node, not the hashing.""" + hashes = [] + stack = [(False, node)] + while stack: + combine, current = stack.pop() + if combine: + first = hashes.pop() + rest = hashes.pop() + hashes.append(hashlib.sha256(b"\x02" + first + rest).digest()) + elif is_pair(current): + stack.append((True, None)) + stack.append((False, current[0])) + stack.append((False, current[1])) + else: + hashes.append(hashlib.sha256(b"\x01" + current).digest()) + return hashes[0] + + +def tagged_hash(tag, data): + """BIP340's tagged hash: SHA-256 of the tag's digest twice, then + the data. tag is the ASCII tag name.""" + tag_hash = hashlib.sha256(tag.encode("ascii")).digest() + return hashlib.sha256(tag_hash + tag_hash + data).digest() + + +def compact_size(n): + """Bitcoin's variable-length count prefix.""" + if n < 0xFD: + return n.to_bytes(1, "little") + if n <= 0xFFFF: + return b"\xfd" + n.to_bytes(2, "little") + if n <= 0xFFFFFFFF: + return b"\xfe" + n.to_bytes(4, "little") + return b"\xff" + n.to_bytes(8, "little") + + +def tapleaf_hash(leaf_version, leaf_script): + """BIP341's leaf hash: the TapLeaf tagged hash of the leaf version + byte, the compact-size length of the leaf script, and the leaf + script.""" + return tagged_hash( + "TapLeaf", bytes([leaf_version]) + compact_size(len(leaf_script)) + leaf_script + ) + + +def merkle_root(tapleaf, path): + """BIP341's path fold: starting from the leaf hash, each 32-byte + path element is combined under TapBranch with the running value, + the two sorted lexicographically. An empty path leaves the leaf + hash as the root.""" + node = tapleaf + for offset in range(0, len(path), 32): + sibling = path[offset : offset + 32] + pair = node + sibling if node < sibling else sibling + node + node = tagged_hash("TapBranch", pair) + return node + + +def sha_annex(annex): + """BIP341's annex digest: SHA-256 of the compact-size length of + the annex element and the element's bytes, its leading 0x50 + included.""" + return hashlib.sha256(compact_size(len(annex)) + annex).digest() + + +def taproot_script_pubkey(internal_key, root): + """The 34-byte scriptPubKey of an output committing to root under + internal_key, or None when the key does not lift or the tweak + fails, the same value defects taproot_output_key reports.""" + output_key = secp256k1.taproot_output_key(internal_key, root) + if output_key is None: + return None + return b"\x51\x20" + output_key + + +@dataclass(frozen=True) +class ControlBlock: + """A parsed BIP341 control block: the leaf version, the output + key's parity bit, the x-only internal key, and the merkle path as + the concatenated 32-byte elements.""" + + leaf_version: int + parity: int + internal_key: bytes + path: bytes + + @classmethod + def parse(cls, data): + """Splits a control block, else BaseConsensusError: its length + must be 33 plus a multiple of 32, at most 128 path elements.""" + path_length = len(data) - CONTROL_BLOCK_BASE_SIZE + depth, remainder = divmod(path_length, 32) + if path_length < 0 or remainder or depth > MERKLE_PATH_MAX_DEPTH: + raise BaseConsensusError( + f"control block of {len(data)} bytes is not 33 plus 32m, m at most 128" + ) + return cls( + leaf_version=data[0] & LEAF_VERSION_MASK, + parity=data[0] & 1, + internal_key=data[1:CONTROL_BLOCK_BASE_SIZE], + path=data[CONTROL_BLOCK_BASE_SIZE:], + ) + + def identity(self, leaf_script): + """The execution identity this block names for a revealed leaf + script: (tapleaf, merkle root).""" + tapleaf = tapleaf_hash(self.leaf_version, leaf_script) + return tapleaf, merkle_root(tapleaf, self.path) + + def check(self, leaf_script, script_pubkey): + """Base consensus's script-path check: the internal key lifts, + tweaked by the root of this path it gives the spent + scriptPubKey's output key, and the parity bit matches. Returns + (tapleaf, merkle root), else BaseConsensusError.""" + tapleaf, root = self.identity(leaf_script) + tweaked = secp256k1.taproot_output_point(self.internal_key, root) + if tweaked is None: + raise BaseConsensusError( + "internal key lifts to no curve point, or its tweak by this " + "root is no point" + ) + x, y = tweaked + expected = b"\x51\x20" + x.to_bytes(32, "big") + if script_pubkey != expected: + raise BaseConsensusError( + f"spent scriptPubKey {script_pubkey.hex()} is not the taproot " + f"output {expected.hex()} of this control block and leaf" + ) + if y % 2 != self.parity: + raise BaseConsensusError("control block parity bit does not match") + return tapleaf, root diff --git a/python/bitlisp/errors.py b/python/bitlisp/errors.py index 0a2c367..f9ce94d 100644 --- a/python/bitlisp/errors.py +++ b/python/bitlisp/errors.py @@ -8,7 +8,9 @@ CODES = frozenset( { + "bad_witness", "bad_encoding", + "leaf_mismatch", "path_into_atom", "operator_not_atom", "reserved_operator", @@ -48,6 +50,20 @@ ) +class BaseConsensusError(Exception): + """A spend that never reaches BitLisp's rules. + + Base consensus checks a script-path spend's control block before + any rule of this layer runs: its length, that the internal key + lifts to a curve point, and that the key tweaked by the revealed + leaf's merkle root gives the spent scriptPubKey. A witness that + fails those, or whose leaf version is not BitLisp's, is either + rejected by base consensus or is not a BitLisp spend at all, and + no error code of CODES describes it. Distinct from BitLispError + so a vector can never pin one as the other. + """ + + class BitLispError(Exception): """A validation failure. Consensus-relevant only as "invalid". diff --git a/python/bitlisp/secp256k1.py b/python/bitlisp/secp256k1.py index 0e1c26c..947476e 100644 --- a/python/bitlisp/secp256k1.py +++ b/python/bitlisp/secp256k1.py @@ -43,8 +43,8 @@ def _tap_tweak_scalar(internal_key, merkle_root): return int.from_bytes(hashlib.sha256(data).digest(), "big") -def _apply_tweak(point, t): - """The x-only bytes of point + t*G, or None. +def _tweaked_point(point, t): + """The point point + t*G, or None. None when t is not below the group order or the sum is the point at infinity. Both are rejected rather than reduced or folded, so @@ -52,28 +52,44 @@ def _apply_tweak(point, t): """ if t >= N: return None - tweaked = point_add(point, point_mul(t, G)) + return point_add(point, point_mul(t, G)) + + +def _apply_tweak(point, t): + """The x-only bytes of point + t*G, or None as _tweaked_point.""" + tweaked = _tweaked_point(point, t) if tweaked is None: return None return tweaked[0].to_bytes(32, "big") -def taproot_output_key(internal_key, merkle_root): - """The 32-byte x-only taproot output key, or None. +def taproot_output_point(internal_key, merkle_root): + """The taproot output point (x, y), or None. internal_key is 32 bytes and merkle_root 0 or 32 bytes, widths the caller guarantees. Every value defect (an internal key that lifts to no curve point, a tweak scalar at or above the group order, a tweaked point at infinity) returns None, never raises. + The full point, so a caller checking a control block can read + the parity of y. """ if len(internal_key) != 32 or len(merkle_root) not in (0, 32): raise ValueError( - "taproot_output_key requires a 32-byte key and a 0- or 32-byte root" + "taproot_output_point requires a 32-byte key and a 0- or 32-byte root" ) point = lift_x(int.from_bytes(internal_key, "big")) if point is None: return None - return _apply_tweak(point, _tap_tweak_scalar(internal_key, merkle_root)) + return _tweaked_point(point, _tap_tweak_scalar(internal_key, merkle_root)) + + +def taproot_output_key(internal_key, merkle_root): + """The 32-byte x-only taproot output key, or None as + taproot_output_point.""" + tweaked = taproot_output_point(internal_key, merkle_root) + if tweaked is None: + return None + return tweaked[0].to_bytes(32, "big") def lift_x(x): diff --git a/python/bitlisp/spend.py b/python/bitlisp/spend.py new file mode 100644 index 0000000..848b64f --- /dev/null +++ b/python/bitlisp/spend.py @@ -0,0 +1,148 @@ +"""The witness layer: one BitLisp input's spend, from its witness +elements to the condition list it contributes to the transaction. + +A BitLisp spend is a BIP341 script-path spend whose witness carries +four elements in stack order: the solution, the program, the leaf +script, and the control block, with an annex after them only when +the program commits to one. Base consensus authenticates the leaf +against the spent output through the control block before anything +here runs. The stages below then check the witness's shape, decode +the two node elements, check the program against the leaf, evaluate +it over the solution under the budget, and parse the value it +returns as a condition list. The result is the input as the +transaction view carries it, ready for validate_transaction. +""" + +from dataclasses import replace + +from .commitment import ( + ANNEX_TAG, + BITLISP_LEAF_VERSION, + ControlBlock, + sha_annex, + tree_hash, +) +from .conditions import parse_conditions +from .errors import BaseConsensusError, BitLispError +from .machine import run +from .serialize import deserialize +from .validation import check_annex_admission + +# The solution, the program, the leaf script, and the control block. +WITNESS_ELEMENT_COUNT = 4 +LEAF_SCRIPT_SIZE = 32 +# Every element the spender chooses freely (the solution, the program, +# the annex) is bounded here. Bitcoin's legacy script cap, the bound +# the condition layer already places on a scriptPubKey operand. +MAX_WITNESS_ELEMENT_SIZE = 10_000 + + +def split_annex(witness): + """BIP341's annex rule over the witness as the transaction + serializes it: with at least two elements and the last beginning + 0x50, that element is the annex. Returns (elements, annex), the + annex None when there is none.""" + if len(witness) >= 2 and witness[-1][:1] == bytes([ANNEX_TAG]): + return witness[:-1], witness[-1] + return witness, None + + +def read_identity(elements, script_pubkey): + """Base consensus's view of a script-path spend, run before any + rule of this layer: at least two elements, the last a well-formed + control block naming BitLisp's leaf version, whose internal key + tweaked by the revealed leaf's root gives the spent scriptPubKey. + Returns (tapleaf, merkle root, internal key), else + BaseConsensusError. A witness of fewer than two elements is a + key-path spend, not a script-path spend, and a leaf version other + than BitLisp's is a spend this layer never sees.""" + if len(elements) < 2: + raise BaseConsensusError( + f"{len(elements)} witness element(s) is not a script-path spend" + ) + control_block = ControlBlock.parse(elements[-1]) + if control_block.leaf_version != BITLISP_LEAF_VERSION: + raise BaseConsensusError( + f"leaf version {control_block.leaf_version:#04x} is not BitLisp's " + f"{BITLISP_LEAF_VERSION:#04x}" + ) + tapleaf, root = control_block.check(elements[-2], script_pubkey) + return tapleaf, root, control_block.internal_key + + +def evaluate_spend(tx_input, witness, max_cost): + """Runs one input's spend through every per-input stage. + + tx_input is the input as the transaction carries it before + evaluation: outpoint, spent scriptPubKey and amount, sequence, + and no condition list. witness is the input's witness elements + as the transaction serializes them, the control block last and + an annex after it when present. max_cost is the inclusive budget + evaluation and condition parsing share. + + Returns (cost, input): the accrued total and the same input + carrying its condition list, its execution identity, and its + annex hash when the witness carried an annex. Raises + BitLispError when the spend is invalid, under the first failing + stage's code, and BaseConsensusError when base consensus would + reject the spend or it is not a BitLisp spend. + """ + if tx_input.conditions is not None: + raise ValueError("the input already carries a condition list") + elements, annex = split_annex(witness) + tapleaf, root, internal_key = read_identity(elements, tx_input.script_pubkey) + + # Stage 1: the witness shape. Every check here is a width. + if len(elements) != WITNESS_ELEMENT_COUNT: + raise BitLispError( + "bad_witness", + f"a BitLisp witness is {WITNESS_ELEMENT_COUNT} elements beside the " + f"annex, got {len(elements)}", + ) + solution_bytes, program_bytes, leaf_script, _ = elements + if len(leaf_script) != LEAF_SCRIPT_SIZE: + raise BitLispError( + "bad_witness", + f"the leaf script is {LEAF_SCRIPT_SIZE} bytes, got {len(leaf_script)}", + ) + for name, element in ( + ("solution", solution_bytes), + ("program", program_bytes), + ("annex", annex), + ): + if element is not None and len(element) > MAX_WITNESS_ELEMENT_SIZE: + raise BitLispError( + "bad_witness", + f"the {name} element is {len(element)} bytes, above " + f"{MAX_WITNESS_ELEMENT_SIZE}", + ) + + # Stage 2: the program decodes and is the one the leaf commits to. + program = deserialize(program_bytes) + if tree_hash(program) != leaf_script: + raise BitLispError( + "leaf_mismatch", + f"the program's tree hash {tree_hash(program).hex()} is not the leaf " + f"script {leaf_script.hex()}", + ) + + # Stage 3: the solution decodes. Its content is the program's + # business, so there is nothing else to check. + solution = deserialize(solution_bytes) + + # Stage 4: evaluation under the budget. + vm_cost, result = run(program, solution, max_cost) + + # Stage 5: the value is a condition list charged against the same + # budget, and an annex is admitted only under its assert. + cost, conditions = parse_conditions(result, max_cost, cost=vm_cost) + spent = replace( + tx_input, + conditions=conditions, + tapleaf=tapleaf, + merkle_root=root, + internal_key=internal_key, + annex_hash=None if annex is None else sha_annex(annex), + ) + check_annex_admission(spent) + return cost, spent diff --git a/python/bitlisp_tools/compiler.py b/python/bitlisp_tools/compiler.py index 6ee608b..583f197 100644 --- a/python/bitlisp_tools/compiler.py +++ b/python/bitlisp_tools/compiler.py @@ -39,10 +39,10 @@ is not distinguishable from ordinary data by its hash. """ -import hashlib import os from bitlisp import conditions +from bitlisp.commitment import tree_hash from bitlisp.errors import BitLispError from bitlisp.machine import run from bitlisp.operators import OPERATORS @@ -940,27 +940,6 @@ def _operator(self, op, tail, bindings): return (op, _proper_list(*compiled)) -def tree_hash(node): - """The sha256 tree hash of a node, exactly as the sha256tree - operator computes it: leaves hash 0x01 plus the atom, pairs hash - 0x02 plus both child hashes.""" - hashes = [] - stack = [(False, node)] - while stack: - combine, current = stack.pop() - if combine: - first = hashes.pop() - rest = hashes.pop() - hashes.append(hashlib.sha256(b"\x02" + first + rest).digest()) - elif is_pair(current): - stack.append((True, None)) - stack.append((False, current[0])) - stack.append((False, current[1])) - else: - hashes.append(hashlib.sha256(b"\x01" + current).digest()) - return hashes[0] - - def _compile(defs, params, body): """The program node and symbol table for one body against one definitions space, params None for a bare expression.""" From 1422ede5786324ca13df4a9ab47199185bc5ef8a Mon Sep 17 00:00:00 2001 From: Evan Date: Sun, 6 Sep 2026 13:13:05 -0700 Subject: [PATCH 05/17] spec: the challenge tag is spelled BIP0340/challenge The digest-domain table of section 2.4 named the tag BIP340/challenge with first byte 0x07. BIP340 spells its challenge tag BIP0340/challenge, the string secp_verify and the signature asserts hash under, whose digest begins 0x7b. Neither byte is 0x01 or 0x02, so the domain argument stood either way, but the table pins the tags a validator hashes under and must name them as hashed. Found by the test that computes every row of the table from the tag strings the implementation uses. --- spec/SPEC.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spec/SPEC.md b/spec/SPEC.md index 18a6f40..7ec82fc 100644 --- a/spec/SPEC.md +++ b/spec/SPEC.md @@ -152,7 +152,7 @@ each tag digest: | `TapLeaf` | `0xae` | | `TapBranch` | `0x19` | | `TapTweak` | `0xe8` | -| `BIP340/challenge` | `0x07` | +| `BIP0340/challenge` | `0x7b` | | `BitLisp/sig/my_txid` | `0x54` | | `BitLisp/sig/my_scriptpubkey` | `0xe3` | | `BitLisp/sig/my_amount` | `0xdf` | @@ -166,7 +166,7 @@ None is `0x01` or `0x02`, so no tree-hash preimage is a tagged-hash preimage and no tagged-hash preimage is a tree-hash preimage. A tag added to any companion document adds a row here. -`BIP340/challenge` is the challenge tag of BIP340's Verify, which +`BIP0340/challenge` is the challenge tag of BIP340's Verify, which `secp_verify` and the signature asserts compute. The three other digests the companion documents read, the txid and the outputs hash of VALIDATION.md's transaction view and the annex hash of From 843b9a94b32031e7a4d1dcab91ee821205412d4b Mon Sep 17 00:00:00 2001 From: Evan Date: Sun, 6 Sep 2026 13:20:14 -0700 Subject: [PATCH 06/17] vectors: the spend suite A fourth suite, one input's witness through the per-input stages of SPEC.md section 4. A case is the spent scriptPubKey, the witness elements in serialization order, and an explicit budget (section 3.2 is PROVISIONAL until COSTS.md section 9 fixes the function, so each case states its own). Success pins the parsed conditions, the three identity fields read from the control block, the annex hash when there is one, and the cost. A witness base consensus would refuse, or one under another leaf version, is a malformed vector, because the spec gives it no outcome. Four files. witness.json is section 3.1's rules in order and the stage order: the element count with and without an annex, the 0x50-tagged first element that is a solution and not an annex, the leaf script at 0, 31, and 33 bytes, each program and solution decoding failure, leaf_mismatch and what it precedes, the VM error and the parse error each preceding unasserted_annex, and the budget at one below and exactly the total. element-bound.json is rule 4 at and one above MAX_WITNESS_ELEMENT_SIZE for the solution, the program, and the annex, and the bound preceding the stage 2 failures. programs.json is section 3.3's two named programs, the atom 1 and nil, surplus solution data ignored, and section 3.4's annex in both directions at this stage: admitted under its assert, unasserted_annex without it, and the two stage 6 failures (another hash, no annex) passing the input stages as the spec places them. identity.json is sections 2.2 and 2.3: paths of 0, 1, 2, and 128 elements with siblings sorting on both sides of the leaf, two internal keys, both parity bits, cross-checked at generation against the vendored Bitcoin Core tagged hash. Each case states the outcome the spec predicts and the generator checked the implementation against that prediction, so the files pin predicted behavior, not observed. --- tools/run_vectors.py | 89 ++++++- vectors/README.md | 33 +++ vectors/spend/element-bound.json | 139 +++++++++++ vectors/spend/identity.json | 151 ++++++++++++ vectors/spend/programs.json | 269 +++++++++++++++++++++ vectors/spend/witness.json | 394 +++++++++++++++++++++++++++++++ 6 files changed, 1073 insertions(+), 2 deletions(-) create mode 100644 vectors/spend/element-bound.json create mode 100644 vectors/spend/identity.json create mode 100644 vectors/spend/programs.json create mode 100644 vectors/spend/witness.json diff --git a/tools/run_vectors.py b/tools/run_vectors.py index cb0421a..da37e46 100755 --- a/tools/run_vectors.py +++ b/tools/run_vectors.py @@ -9,7 +9,7 @@ { "schema": "bitlisp-vector-v0", - "suite": "vm" | "conditions" | "validation", + "suite": "vm" | "conditions" | "spend" | "validation", "spec": "", "cases": [ ... ] } @@ -33,7 +33,7 @@ sys.path.insert(0, str(REPO_ROOT / "python")) SCHEMA = "bitlisp-vector-v0" -SUITES = ("vm", "conditions", "validation") +SUITES = ("vm", "conditions", "spend", "validation") class VectorError(Exception): @@ -256,6 +256,90 @@ def run_conditions_case(case): raise VectorError(f"expected {expect}, got {outcome}") +def run_spend_case(case): + """One spend case: one input's witness through the per-input + stages, from witness shape to the parsed condition list. + + Case shape, closed like the envelope: + { + "name": "", + "script_pubkey": "", + "witness": ["", ...], + "max_cost": , + "expect": {"conditions": [], + "tapleaf": "<32-byte hex>", + "merkle_root": "<32-byte hex>", + "internal_key": "<32-byte hex>", + "annex_hash": "<32-byte hex, only with an annex>", + "cost": } + or {"error": ""} + } + + witness is the input's elements as the transaction serializes + them, the control block last, an annex after it when present. + max_cost is required: the budget function is not fixed yet, so + every case states the budget it runs under. The condition JSON + is the conditions suite's. tapleaf, merkle_root, and + internal_key are the execution identity read from the control + block, annex_hash the sha_annex digest of the annex. + + Every case is a spend base consensus accepts: a witness base + consensus would reject, or one that is not a BitLisp spend, has + no outcome under this layer and is a malformed vector. + """ + from bitlisp import BaseConsensusError, BitLispError, TxInput, evaluate_spend + from bitlisp.errors import CODES + + required = {"name", "script_pubkey", "witness", "max_cost", "expect"} + keys = set(case) + if missing := required - keys: + raise VectorError(f"missing keys {sorted(missing)}") + if extra := keys - required: + raise VectorError(f"unknown keys {sorted(extra)}") + expect = case["expect"] + success_keys = {"conditions", "tapleaf", "merkle_root", "internal_key", "cost"} + if not isinstance(expect, dict) or set(expect) not in ( + success_keys, + success_keys | {"annex_hash"}, + {"error"}, + ): + raise VectorError( + "expect must be exactly {conditions, tapleaf, merkle_root, " + "internal_key, cost}, those plus annex_hash, or {error}" + ) + if "error" in expect and expect["error"] not in CODES: + raise VectorError(f"unknown expected error code {expect['error']!r}") + if not isinstance(case["witness"], list): + raise VectorError("witness must be a list of hex elements") + # The outpoint, amount, and sequence are filler: nothing before + # the transaction stage reads them. + tx_input = TxInput( + txid=b"\x00" * 32, + index=0, + script_pubkey=bytes.fromhex(case["script_pubkey"]), + amount=1, + sequence=0xFFFFFFFF, + ) + witness = [bytes.fromhex(element) for element in case["witness"]] + try: + cost, spent = evaluate_spend(tx_input, witness, case["max_cost"]) + outcome = { + "conditions": [_condition_json(c) for c in spent.conditions], + "tapleaf": spent.tapleaf.hex(), + "merkle_root": spent.merkle_root.hex(), + "internal_key": spent.internal_key.hex(), + "cost": cost, + } + if spent.annex_hash is not None: + outcome["annex_hash"] = spent.annex_hash.hex() + except BaseConsensusError as exc: + raise VectorError(f"outside BitLisp, base consensus decides: {exc}") from None + except BitLispError as exc: + outcome = {"error": exc.code} + if outcome != expect: + raise VectorError(f"expected {expect}, got {outcome}") + + def run_validation_case(case): """One validation case: validate a transaction's condition lists. @@ -346,6 +430,7 @@ def run_suite(envelope, path): RUNNERS = { "vm": _make_suite_runner(run_vm_case), "conditions": _make_suite_runner(run_conditions_case), + "spend": _make_suite_runner(run_spend_case), "validation": _make_suite_runner(run_validation_case), } diff --git a/vectors/README.md b/vectors/README.md index 8dd9158..82967bc 100644 --- a/vectors/README.md +++ b/vectors/README.md @@ -11,6 +11,7 @@ why the vector was wrong (CLAUDE.md). | --- | --- | --- | | `vm/` | `vm` | (program, witness arguments) to (result, cost) or error | | `conditions/` | `conditions` | condition-list parsing and validation | +| `spend/` | `spend` | one input's witness through the per-input stages: shape, decoding, the leaf check, evaluation, the condition list, the annex rule | | `validation/` | `validation` | tx-context validation, including the adversarial regression corpus | | `upstream/` | `tools/run_upstream.py` (clvm), unit suite (bip340, bip341) | Upstream vectors vendored as data, original format, provenance headers required | @@ -85,6 +86,38 @@ order, amounts as integers, all other fields hex: ANNOUNCE is `"assurer"` and `"requirer_commitment"`. Every rejection rule in CONDITIONS.md section 1 and VALIDATION.md rule 6 has at least one case. +## spend case shape + +```json +{ + "name": "unique within the file", + "script_pubkey": "", + "witness": ["", "", "", ""], + "max_cost": 10000000, + "expect": { + "conditions": [], + "tapleaf": "", + "merkle_root": "", + "internal_key": "", + "cost": 244 + } +} +``` + +`witness` is the input's elements as the transaction serializes +them, the control block last and an annex after it when the case +carries one. `max_cost` is required: the budget function of +COSTS.md section 9 is not fixed, so every case states the budget it +runs under. `expect` is the success shape above, with `annex_hash` +added when the witness carries an annex, or `{"error": ""}`. +`conditions` uses the conditions suite's JSON forms, and the three +identity fields are what the control block and leaf script read to. +Every case is a spend base consensus accepts: the runner rejects as +malformed a witness base consensus would refuse or one under another +leaf version, because SPEC.md assigns those no outcome. Every case +in `spend/identity.json` was cross-checked against the vendored +Bitcoin Core tagged hash when written. + ## validation case shape ```json diff --git a/vectors/spend/element-bound.json b/vectors/spend/element-bound.json new file mode 100644 index 0000000..b35a0bd --- /dev/null +++ b/vectors/spend/element-bound.json @@ -0,0 +1,139 @@ +{ + "schema": "bitlisp-vector-v0", + "suite": "spend", + "spec": "SPEC.md section 3.1 rule 4, MAX_WITNESS_ELEMENT_SIZE over the solution, the program, and the annex", + "cases": [ + { + "name": "solution_at_bound", + "script_pubkey": "512019a1711d0c402084f7e8814adda58a2c37549f8345d69376de4029af191c916c", + "witness": [ + "e0270d5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a", + "ff0180", + "ba4484b961b7a2369d948d06c55b64bdbfaffb326bc13b490ab1215dd33d8d46", + "d050929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0" + ], + "max_cost": 10000000, + "expect": { + "conditions": [], + "tapleaf": "2b270110b679efa9f8555b942c8d83a6b80303ec3dee632075600e54947b9a25", + "merkle_root": "2b270110b679efa9f8555b942c8d83a6b80303ec3dee632075600e54947b9a25", + "internal_key": "50929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0", + "cost": 20 + } + }, + { + "name": "solution_above_bound", + "script_pubkey": "512019a1711d0c402084f7e8814adda58a2c37549f8345d69376de4029af191c916c", + "witness": [ + "e0270e5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a", + "ff0180", + "ba4484b961b7a2369d948d06c55b64bdbfaffb326bc13b490ab1215dd33d8d46", + "d050929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0" + ], + "max_cost": 10000000, + "expect": { + "error": "bad_witness" + } + }, + { + "name": "program_at_bound", + "script_pubkey": "51209b37163ddf1ffd9b01b8d7333e5000a995617ef824d9e8b7676880bd077dd4ab", + "witness": [ + "80", + "ff02ffff0180ffff01e027035a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a80", + "d8307a146934e501e4aeb4e0221f73d54eeab2fdc316826f6ade611efff4e0b9", + "d050929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0" + ], + "max_cost": 10000000, + "expect": { + "conditions": [], + "tapleaf": "cafe9715f07152400ced1769765868713c9526b5f6423e1abe3651473fd04178", + "merkle_root": "cafe9715f07152400ced1769765868713c9526b5f6423e1abe3651473fd04178", + "internal_key": "50929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0", + "cost": 175 + } + }, + { + "name": "program_above_bound", + "script_pubkey": "512071b08ce43a7cee35c4240f47192f185d81a33b56cfc3e6d83e1630b616b44da4", + "witness": [ + "80", + "ff02ffff0180ffff01e027045a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a80", + "69db8e5a3a564d3b1399b336d435fa2a7af6589869240b099a2a480381e0f88c", + "d150929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0" + ], + "max_cost": 10000000, + "expect": { + "error": "bad_witness" + } + }, + { + "name": "annex_at_bound", + "script_pubkey": "512035c4da5c6fd860279664e5e3d09516d7828ac0b1e8878fbeefbb22913962efc3", + "witness": [ + "80", + "ff01ffff39ffa09fa3358562e69a6f00eebdda3f15112d7451c39183dd1ac53e2de1ba0132ab688080", + "5fdcab84849c47ce8c9ad9ff8ca6c4b236471a71df19f402477997160b93f7c4", + "d150929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0", + "505a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a" + ], + "max_cost": 10000000, + "expect": { + "conditions": [ + { + "opcode": 57, + "annex_hash": "9fa3358562e69a6f00eebdda3f15112d7451c39183dd1ac53e2de1ba0132ab68" + } + ], + "tapleaf": "fa886100e04af6be93af15fa3be842259a75b6c4284e28f59466b3e724e19a19", + "merkle_root": "fa886100e04af6be93af15fa3be842259a75b6c4284e28f59466b3e724e19a19", + "internal_key": "50929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0", + "cost": 220, + "annex_hash": "9fa3358562e69a6f00eebdda3f15112d7451c39183dd1ac53e2de1ba0132ab68" + } + }, + { + "name": "annex_above_bound", + "script_pubkey": "51209dea0dcdccaebcefcc296276ab07a0fc1bdd8bc9047bb7501648fd5637d9f97b", + "witness": [ + "80", + "ff01ffff39ffa0a272d566b47d3c9f82c6bd8efec7489a6d737c975727eb552ab68a1755e3891e8080", + "0a66bbec0d8644bfc5eedc41b4381d1a126649787ce5f0c92422d412265ff50e", + "d050929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0", + "505a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a" + ], + "max_cost": 10000000, + "expect": { + "error": "bad_witness" + } + }, + { + "name": "oversized_program_wins_over_leaf_mismatch", + "script_pubkey": "5120864ac98761331f672c01124a5a08e77402420ff7e471bd38cf5ce354a104a194", + "witness": [ + "ffff33ff8203e88080", + "ff02ffff0180ffff01e027045a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a80", + "9dcf97a184f32623d11a73124ceb99a5709b083721e878a16d78f596718ba7b2", + "d050929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0" + ], + "max_cost": 10000000, + "expect": { + "error": "bad_witness" + } + }, + { + "name": "oversized_solution_wins_over_bad_program", + "script_pubkey": "5120864ac98761331f672c01124a5a08e77402420ff7e471bd38cf5ce354a104a194", + "witness": [ + "e0270e5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a", + "", + "9dcf97a184f32623d11a73124ceb99a5709b083721e878a16d78f596718ba7b2", + "d050929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0" + ], + "max_cost": 10000000, + "expect": { + "error": "bad_witness" + } + } + ] +} diff --git a/vectors/spend/identity.json b/vectors/spend/identity.json new file mode 100644 index 0000000..428d54f --- /dev/null +++ b/vectors/spend/identity.json @@ -0,0 +1,151 @@ +{ + "schema": "bitlisp-vector-v0", + "suite": "spend", + "spec": "SPEC.md sections 2.2 and 2.3 (the leaf hash and the execution identity read from the control block)", + "cases": [ + { + "name": "single_leaf", + "script_pubkey": "512019a1711d0c402084f7e8814adda58a2c37549f8345d69376de4029af191c916c", + "witness": [ + "80", + "ff0180", + "ba4484b961b7a2369d948d06c55b64bdbfaffb326bc13b490ab1215dd33d8d46", + "d050929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0" + ], + "max_cost": 10000000, + "expect": { + "conditions": [], + "tapleaf": "2b270110b679efa9f8555b942c8d83a6b80303ec3dee632075600e54947b9a25", + "merkle_root": "2b270110b679efa9f8555b942c8d83a6b80303ec3dee632075600e54947b9a25", + "internal_key": "50929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0", + "cost": 20 + } + }, + { + "name": "sibling_sorting_before_the_leaf", + "script_pubkey": "512054e1c98d3ec9e7c7050da64a39d1574a6efbec7aef2de766eb86a1fd0bc16705", + "witness": [ + "80", + "ff0180", + "ba4484b961b7a2369d948d06c55b64bdbfaffb326bc13b490ab1215dd33d8d46", + "d150929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac00000000000000000000000000000000000000000000000000000000000000000" + ], + "max_cost": 10000000, + "expect": { + "conditions": [], + "tapleaf": "2b270110b679efa9f8555b942c8d83a6b80303ec3dee632075600e54947b9a25", + "merkle_root": "e6dbccf40508a8e9f51b5fc1f25fdd5547595e4b6afe4b802d79d31abfbc4a78", + "internal_key": "50929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0", + "cost": 20 + } + }, + { + "name": "sibling_sorting_after_the_leaf", + "script_pubkey": "5120bbb01b4ad56dfafa644c0599e9fbaa6ff4f48f79791d7a5c8b0ef592a7e23102", + "witness": [ + "80", + "ff0180", + "ba4484b961b7a2369d948d06c55b64bdbfaffb326bc13b490ab1215dd33d8d46", + "d150929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" + ], + "max_cost": 10000000, + "expect": { + "conditions": [], + "tapleaf": "2b270110b679efa9f8555b942c8d83a6b80303ec3dee632075600e54947b9a25", + "merkle_root": "16bde6e4d90c151e361a22778455e11c2255375bd40405cf08c58cebec8f3639", + "internal_key": "50929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0", + "cost": 20 + } + }, + { + "name": "path_of_two", + "script_pubkey": "51202422d201b2f9a10cb95ac0bf12394c3472e5a57539a4df22f0d834fcdbe6af5b", + "witness": [ + "80", + "ff0180", + "ba4484b961b7a2369d948d06c55b64bdbfaffb326bc13b490ab1215dd33d8d46", + "d150929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac00000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" + ], + "max_cost": 10000000, + "expect": { + "conditions": [], + "tapleaf": "2b270110b679efa9f8555b942c8d83a6b80303ec3dee632075600e54947b9a25", + "merkle_root": "cd97713ccb9f24cb448b0c774da0eb62a64030c2e078e8c33dcc13753573d2bf", + "internal_key": "50929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0", + "cost": 20 + } + }, + { + "name": "path_of_two_reversed", + "script_pubkey": "51203ce1f72a27f2058c48d646b803a67a7c2692aa4a48604ecafb6a9c18965c2976", + "witness": [ + "80", + "ff0180", + "ba4484b961b7a2369d948d06c55b64bdbfaffb326bc13b490ab1215dd33d8d46", + "d050929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000" + ], + "max_cost": 10000000, + "expect": { + "conditions": [], + "tapleaf": "2b270110b679efa9f8555b942c8d83a6b80303ec3dee632075600e54947b9a25", + "merkle_root": "81667e21ec1f98223da8c672a33b494f149065e0e83dab1e8303e699801d7bf1", + "internal_key": "50929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0", + "cost": 20 + } + }, + { + "name": "path_of_128", + "script_pubkey": "5120007cdaa916b4e4bec06e67d2431b8e6b51289d92fd36d0fbbdb22dd751269d74", + "witness": [ + "80", + "ff0180", + "ba4484b961b7a2369d948d06c55b64bdbfaffb326bc13b490ab1215dd33d8d46", + "d050929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000009000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000b000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000d000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000f0000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001100000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000013000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000150000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000001700000000000000000000000000000000000000000000000000000000000000180000000000000000000000000000000000000000000000000000000000000019000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000001b000000000000000000000000000000000000000000000000000000000000001c000000000000000000000000000000000000000000000000000000000000001d000000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000001f0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002100000000000000000000000000000000000000000000000000000000000000220000000000000000000000000000000000000000000000000000000000000023000000000000000000000000000000000000000000000000000000000000002400000000000000000000000000000000000000000000000000000000000000250000000000000000000000000000000000000000000000000000000000000026000000000000000000000000000000000000000000000000000000000000002700000000000000000000000000000000000000000000000000000000000000280000000000000000000000000000000000000000000000000000000000000029000000000000000000000000000000000000000000000000000000000000002a000000000000000000000000000000000000000000000000000000000000002b000000000000000000000000000000000000000000000000000000000000002c000000000000000000000000000000000000000000000000000000000000002d000000000000000000000000000000000000000000000000000000000000002e000000000000000000000000000000000000000000000000000000000000002f0000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000003100000000000000000000000000000000000000000000000000000000000000320000000000000000000000000000000000000000000000000000000000000033000000000000000000000000000000000000000000000000000000000000003400000000000000000000000000000000000000000000000000000000000000350000000000000000000000000000000000000000000000000000000000000036000000000000000000000000000000000000000000000000000000000000003700000000000000000000000000000000000000000000000000000000000000380000000000000000000000000000000000000000000000000000000000000039000000000000000000000000000000000000000000000000000000000000003a000000000000000000000000000000000000000000000000000000000000003b000000000000000000000000000000000000000000000000000000000000003c000000000000000000000000000000000000000000000000000000000000003d000000000000000000000000000000000000000000000000000000000000003e000000000000000000000000000000000000000000000000000000000000003f0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000004100000000000000000000000000000000000000000000000000000000000000420000000000000000000000000000000000000000000000000000000000000043000000000000000000000000000000000000000000000000000000000000004400000000000000000000000000000000000000000000000000000000000000450000000000000000000000000000000000000000000000000000000000000046000000000000000000000000000000000000000000000000000000000000004700000000000000000000000000000000000000000000000000000000000000480000000000000000000000000000000000000000000000000000000000000049000000000000000000000000000000000000000000000000000000000000004a000000000000000000000000000000000000000000000000000000000000004b000000000000000000000000000000000000000000000000000000000000004c000000000000000000000000000000000000000000000000000000000000004d000000000000000000000000000000000000000000000000000000000000004e000000000000000000000000000000000000000000000000000000000000004f0000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000005100000000000000000000000000000000000000000000000000000000000000520000000000000000000000000000000000000000000000000000000000000053000000000000000000000000000000000000000000000000000000000000005400000000000000000000000000000000000000000000000000000000000000550000000000000000000000000000000000000000000000000000000000000056000000000000000000000000000000000000000000000000000000000000005700000000000000000000000000000000000000000000000000000000000000580000000000000000000000000000000000000000000000000000000000000059000000000000000000000000000000000000000000000000000000000000005a000000000000000000000000000000000000000000000000000000000000005b000000000000000000000000000000000000000000000000000000000000005c000000000000000000000000000000000000000000000000000000000000005d000000000000000000000000000000000000000000000000000000000000005e000000000000000000000000000000000000000000000000000000000000005f0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000006100000000000000000000000000000000000000000000000000000000000000620000000000000000000000000000000000000000000000000000000000000063000000000000000000000000000000000000000000000000000000000000006400000000000000000000000000000000000000000000000000000000000000650000000000000000000000000000000000000000000000000000000000000066000000000000000000000000000000000000000000000000000000000000006700000000000000000000000000000000000000000000000000000000000000680000000000000000000000000000000000000000000000000000000000000069000000000000000000000000000000000000000000000000000000000000006a000000000000000000000000000000000000000000000000000000000000006b000000000000000000000000000000000000000000000000000000000000006c000000000000000000000000000000000000000000000000000000000000006d000000000000000000000000000000000000000000000000000000000000006e000000000000000000000000000000000000000000000000000000000000006f0000000000000000000000000000000000000000000000000000000000000070000000000000000000000000000000000000000000000000000000000000007100000000000000000000000000000000000000000000000000000000000000720000000000000000000000000000000000000000000000000000000000000073000000000000000000000000000000000000000000000000000000000000007400000000000000000000000000000000000000000000000000000000000000750000000000000000000000000000000000000000000000000000000000000076000000000000000000000000000000000000000000000000000000000000007700000000000000000000000000000000000000000000000000000000000000780000000000000000000000000000000000000000000000000000000000000079000000000000000000000000000000000000000000000000000000000000007a000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007c000000000000000000000000000000000000000000000000000000000000007d000000000000000000000000000000000000000000000000000000000000007e000000000000000000000000000000000000000000000000000000000000007f" + ], + "max_cost": 10000000, + "expect": { + "conditions": [], + "tapleaf": "2b270110b679efa9f8555b942c8d83a6b80303ec3dee632075600e54947b9a25", + "merkle_root": "5585b6215f5383d2d6abe31f98466b4c0f3abd94d41f19ee0452bf482c0c8ccd", + "internal_key": "50929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0", + "cost": 20 + } + }, + { + "name": "internal_key_generator", + "script_pubkey": "51207998a7f41a86b91d1ac603938ef2abcc557ff6a053c6c8ca4418edbf8db5d425", + "witness": [ + "80", + "ff0180", + "ba4484b961b7a2369d948d06c55b64bdbfaffb326bc13b490ab1215dd33d8d46", + "d079be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798" + ], + "max_cost": 10000000, + "expect": { + "conditions": [], + "tapleaf": "2b270110b679efa9f8555b942c8d83a6b80303ec3dee632075600e54947b9a25", + "merkle_root": "2b270110b679efa9f8555b942c8d83a6b80303ec3dee632075600e54947b9a25", + "internal_key": "79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798", + "cost": 20 + } + }, + { + "name": "internal_key_generator_with_path", + "script_pubkey": "51208983cccd35231c7aae294d105de0bccaab854feb0b484bf05edb69f0194e6533", + "witness": [ + "80", + "ff0180", + "ba4484b961b7a2369d948d06c55b64bdbfaffb326bc13b490ab1215dd33d8d46", + "d079be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" + ], + "max_cost": 10000000, + "expect": { + "conditions": [], + "tapleaf": "2b270110b679efa9f8555b942c8d83a6b80303ec3dee632075600e54947b9a25", + "merkle_root": "16bde6e4d90c151e361a22778455e11c2255375bd40405cf08c58cebec8f3639", + "internal_key": "79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798", + "cost": 20 + } + } + ] +} diff --git a/vectors/spend/programs.json b/vectors/spend/programs.json new file mode 100644 index 0000000..e23c2d6 --- /dev/null +++ b/vectors/spend/programs.json @@ -0,0 +1,269 @@ +{ + "schema": "bitlisp-vector-v0", + "suite": "spend", + "spec": "SPEC.md section 3.3 (evaluation, the two named programs) and 3.4 (the annex)", + "cases": [ + { + "name": "atom_one_returns_the_solution", + "script_pubkey": "5120864ac98761331f672c01124a5a08e77402420ff7e471bd38cf5ce354a104a194", + "witness": [ + "ffff33ff8203e88080", + "01", + "9dcf97a184f32623d11a73124ceb99a5709b083721e878a16d78f596718ba7b2", + "d050929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0" + ], + "max_cost": 10000000, + "expect": { + "conditions": [ + { + "opcode": 51, + "amount": 1000 + } + ], + "tapleaf": "dde54461ef9453a9d235b60142c77f6680d0243ec4a02d206750059e8ea08b95", + "merkle_root": "dde54461ef9453a9d235b60142c77f6680d0243ec4a02d206750059e8ea08b95", + "internal_key": "50929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0", + "cost": 244 + } + }, + { + "name": "atom_one_create_output", + "script_pubkey": "5120864ac98761331f672c01124a5a08e77402420ff7e471bd38cf5ce354a104a194", + "witness": [ + "ffff01ff51ff8201f48080", + "01", + "9dcf97a184f32623d11a73124ceb99a5709b083721e878a16d78f596718ba7b2", + "d050929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0" + ], + "max_cost": 10000000, + "expect": { + "conditions": [ + { + "opcode": 1, + "script_pubkey": "51", + "amount": 500 + } + ], + "tapleaf": "dde54461ef9453a9d235b60142c77f6680d0243ec4a02d206750059e8ea08b95", + "merkle_root": "dde54461ef9453a9d235b60142c77f6680d0243ec4a02d206750059e8ea08b95", + "internal_key": "50929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0", + "cost": 1350044 + } + }, + { + "name": "atom_one_empty_solution_list", + "script_pubkey": "5120864ac98761331f672c01124a5a08e77402420ff7e471bd38cf5ce354a104a194", + "witness": [ + "80", + "01", + "9dcf97a184f32623d11a73124ceb99a5709b083721e878a16d78f596718ba7b2", + "d050929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0" + ], + "max_cost": 10000000, + "expect": { + "conditions": [], + "tapleaf": "dde54461ef9453a9d235b60142c77f6680d0243ec4a02d206750059e8ea08b95", + "merkle_root": "dde54461ef9453a9d235b60142c77f6680d0243ec4a02d206750059e8ea08b95", + "internal_key": "50929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0", + "cost": 44 + } + }, + { + "name": "nil_program_ignores_the_solution", + "script_pubkey": "512096dee59551cbe424a6d57640ece743a7a833f2f758f41ba5e46b82b8b11653c0", + "witness": [ + "ffff33ff8203e88080", + "80", + "4bf5122f344554c53bde2ebb8cd2b7e3d1600ad631c385a5d7cce23c7785459a", + "d050929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0" + ], + "max_cost": 10000000, + "expect": { + "conditions": [], + "tapleaf": "b7aaee8eedc711c3450ed46088b2a5d01412b028ad0aad45a2446e6d669b161b", + "merkle_root": "b7aaee8eedc711c3450ed46088b2a5d01412b028ad0aad45a2446e6d669b161b", + "internal_key": "50929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0", + "cost": 44 + } + }, + { + "name": "nil_program_nil_solution", + "script_pubkey": "512096dee59551cbe424a6d57640ece743a7a833f2f758f41ba5e46b82b8b11653c0", + "witness": [ + "80", + "80", + "4bf5122f344554c53bde2ebb8cd2b7e3d1600ad631c385a5d7cce23c7785459a", + "d050929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0" + ], + "max_cost": 10000000, + "expect": { + "conditions": [], + "tapleaf": "b7aaee8eedc711c3450ed46088b2a5d01412b028ad0aad45a2446e6d669b161b", + "merkle_root": "b7aaee8eedc711c3450ed46088b2a5d01412b028ad0aad45a2446e6d669b161b", + "internal_key": "50929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0", + "cost": 44 + } + }, + { + "name": "surplus_solution_data_ignored", + "script_pubkey": "51209efdab4356dd725b3b863f5e0f388312b0c6cdfd4f42be8f5bc58e6f77bdbf3c", + "witness": [ + "ffff33ff8203e880ff846a756e6bffff846d6f72658080", + "ff04ffff05ff0180ff8080", + "e6f106494935a5e88928a15d205888ee8ae9f2d6408c779bcd6e9387ec6cde0d", + "d150929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0" + ], + "max_cost": 10000000, + "expect": { + "conditions": [ + { + "opcode": 51, + "amount": 1000 + } + ], + "tapleaf": "f6ed9df9774014bcbf1234139037e56edc1e377b560c5fa4386ba8e7bd29f8da", + "merkle_root": "f6ed9df9774014bcbf1234139037e56edc1e377b560c5fa4386ba8e7bd29f8da", + "internal_key": "50929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0", + "cost": 370 + } + }, + { + "name": "annex_under_its_assert", + "script_pubkey": "51209e67b0bf81dc0efc143e998bf0a02a3265c883ad8b4503c3bb76af15ce06e899", + "witness": [ + "80", + "ff01ffff39ffa09ead2a42d43638f5cd0d2f61f94c8786211ea1d678445db915507c61bbcbf07c8080", + "618c6363e0187cc45d9821c1dc99bb2f5594f74c8dda0d7a1c3e696110af14ba", + "d050929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0", + "50616e6e6578" + ], + "max_cost": 10000000, + "expect": { + "conditions": [ + { + "opcode": 57, + "annex_hash": "9ead2a42d43638f5cd0d2f61f94c8786211ea1d678445db915507c61bbcbf07c" + } + ], + "tapleaf": "324754e6f358d1ebd1770d9f3082d95a70d9037ed9cc41285552d13c97ebcd55", + "merkle_root": "324754e6f358d1ebd1770d9f3082d95a70d9037ed9cc41285552d13c97ebcd55", + "internal_key": "50929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0", + "cost": 220, + "annex_hash": "9ead2a42d43638f5cd0d2f61f94c8786211ea1d678445db915507c61bbcbf07c" + } + }, + { + "name": "annex_without_the_assert", + "script_pubkey": "512019a1711d0c402084f7e8814adda58a2c37549f8345d69376de4029af191c916c", + "witness": [ + "80", + "ff0180", + "ba4484b961b7a2369d948d06c55b64bdbfaffb326bc13b490ab1215dd33d8d46", + "d050929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0", + "50616e6e6578" + ], + "max_cost": 10000000, + "expect": { + "error": "unasserted_annex" + } + }, + { + "name": "annex_assert_with_another_hash_passes_the_input_stages", + "script_pubkey": "5120b4c603932495f0c04e4106350a84e95824b8ede80f126062d9c4b765ec146f0f", + "witness": [ + "80", + "ff01ffff39ffa011111111111111111111111111111111111111111111111111111111111111118080", + "32b0cc9c557f37ef5c93b02d6af2fdd6f7dbb48aa4ec14edb2065d9bdc11e870", + "d050929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0", + "50616e6e6578" + ], + "max_cost": 10000000, + "expect": { + "conditions": [ + { + "opcode": 57, + "annex_hash": "1111111111111111111111111111111111111111111111111111111111111111" + } + ], + "tapleaf": "98f201b8f9c6a0fbf356d88875de782354270514e91183a2c77a147d8371ec58", + "merkle_root": "98f201b8f9c6a0fbf356d88875de782354270514e91183a2c77a147d8371ec58", + "internal_key": "50929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0", + "cost": 220, + "annex_hash": "9ead2a42d43638f5cd0d2f61f94c8786211ea1d678445db915507c61bbcbf07c" + } + }, + { + "name": "annex_assert_without_an_annex_passes_the_input_stages", + "script_pubkey": "51209e67b0bf81dc0efc143e998bf0a02a3265c883ad8b4503c3bb76af15ce06e899", + "witness": [ + "80", + "ff01ffff39ffa09ead2a42d43638f5cd0d2f61f94c8786211ea1d678445db915507c61bbcbf07c8080", + "618c6363e0187cc45d9821c1dc99bb2f5594f74c8dda0d7a1c3e696110af14ba", + "d050929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0" + ], + "max_cost": 10000000, + "expect": { + "conditions": [ + { + "opcode": 57, + "annex_hash": "9ead2a42d43638f5cd0d2f61f94c8786211ea1d678445db915507c61bbcbf07c" + } + ], + "tapleaf": "324754e6f358d1ebd1770d9f3082d95a70d9037ed9cc41285552d13c97ebcd55", + "merkle_root": "324754e6f358d1ebd1770d9f3082d95a70d9037ed9cc41285552d13c97ebcd55", + "internal_key": "50929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0", + "cost": 220 + } + }, + { + "name": "annex_of_one_byte", + "script_pubkey": "5120444277d609b62024902467d5c5abf8f89728c83647e4a12dde21805e0fb365af", + "witness": [ + "80", + "ff01ffff39ffa02847213288f0988543a76512fab09684131809d98baa8b93c2cd8a03a0e31d418080", + "70dbc8e16903966f7b3715ddd86ceb0dcf465e5c3f627d1669d8ac5d4778ce41", + "d150929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0", + "50" + ], + "max_cost": 10000000, + "expect": { + "conditions": [ + { + "opcode": 57, + "annex_hash": "2847213288f0988543a76512fab09684131809d98baa8b93c2cd8a03a0e31d41" + } + ], + "tapleaf": "9f27f63b8a1e9df53fcac186594eca00e8ece5a905719edf7f21d76618058147", + "merkle_root": "9f27f63b8a1e9df53fcac186594eca00e8ece5a905719edf7f21d76618058147", + "internal_key": "50929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0", + "cost": 220, + "annex_hash": "2847213288f0988543a76512fab09684131809d98baa8b93c2cd8a03a0e31d41" + } + }, + { + "name": "spender_supplied_annex_assert", + "script_pubkey": "5120864ac98761331f672c01124a5a08e77402420ff7e471bd38cf5ce354a104a194", + "witness": [ + "ffff39ffa09ead2a42d43638f5cd0d2f61f94c8786211ea1d678445db915507c61bbcbf07c8080", + "01", + "9dcf97a184f32623d11a73124ceb99a5709b083721e878a16d78f596718ba7b2", + "d050929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0", + "50616e6e6578" + ], + "max_cost": 10000000, + "expect": { + "conditions": [ + { + "opcode": 57, + "annex_hash": "9ead2a42d43638f5cd0d2f61f94c8786211ea1d678445db915507c61bbcbf07c" + } + ], + "tapleaf": "dde54461ef9453a9d235b60142c77f6680d0243ec4a02d206750059e8ea08b95", + "merkle_root": "dde54461ef9453a9d235b60142c77f6680d0243ec4a02d206750059e8ea08b95", + "internal_key": "50929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0", + "cost": 244, + "annex_hash": "9ead2a42d43638f5cd0d2f61f94c8786211ea1d678445db915507c61bbcbf07c" + } + } + ] +} diff --git a/vectors/spend/witness.json b/vectors/spend/witness.json new file mode 100644 index 0000000..4ea91dc --- /dev/null +++ b/vectors/spend/witness.json @@ -0,0 +1,394 @@ +{ + "schema": "bitlisp-vector-v0", + "suite": "spend", + "spec": "SPEC.md section 3.1 (the witness rules in order), 3.2 (an explicit budget), and the stage order of section 4", + "cases": [ + { + "name": "four_elements", + "script_pubkey": "5120864ac98761331f672c01124a5a08e77402420ff7e471bd38cf5ce354a104a194", + "witness": [ + "ffff33ff8203e88080", + "01", + "9dcf97a184f32623d11a73124ceb99a5709b083721e878a16d78f596718ba7b2", + "d050929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0" + ], + "max_cost": 10000000, + "expect": { + "conditions": [ + { + "opcode": 51, + "amount": 1000 + } + ], + "tapleaf": "dde54461ef9453a9d235b60142c77f6680d0243ec4a02d206750059e8ea08b95", + "merkle_root": "dde54461ef9453a9d235b60142c77f6680d0243ec4a02d206750059e8ea08b95", + "internal_key": "50929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0", + "cost": 244 + } + }, + { + "name": "five_elements", + "script_pubkey": "5120864ac98761331f672c01124a5a08e77402420ff7e471bd38cf5ce354a104a194", + "witness": [ + "80", + "ffff33ff8203e88080", + "01", + "9dcf97a184f32623d11a73124ceb99a5709b083721e878a16d78f596718ba7b2", + "d050929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0" + ], + "max_cost": 10000000, + "expect": { + "error": "bad_witness" + } + }, + { + "name": "three_elements", + "script_pubkey": "5120864ac98761331f672c01124a5a08e77402420ff7e471bd38cf5ce354a104a194", + "witness": [ + "01", + "9dcf97a184f32623d11a73124ceb99a5709b083721e878a16d78f596718ba7b2", + "d050929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0" + ], + "max_cost": 10000000, + "expect": { + "error": "bad_witness" + } + }, + { + "name": "two_elements", + "script_pubkey": "5120864ac98761331f672c01124a5a08e77402420ff7e471bd38cf5ce354a104a194", + "witness": [ + "9dcf97a184f32623d11a73124ceb99a5709b083721e878a16d78f596718ba7b2", + "d050929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0" + ], + "max_cost": 10000000, + "expect": { + "error": "bad_witness" + } + }, + { + "name": "annex_is_not_a_fifth_element", + "script_pubkey": "5120864ac98761331f672c01124a5a08e77402420ff7e471bd38cf5ce354a104a194", + "witness": [ + "ffff33ff8203e88080", + "01", + "9dcf97a184f32623d11a73124ceb99a5709b083721e878a16d78f596718ba7b2", + "d050929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0", + "50616e6e6578" + ], + "max_cost": 10000000, + "expect": { + "error": "unasserted_annex" + } + }, + { + "name": "annex_beside_three_elements", + "script_pubkey": "5120864ac98761331f672c01124a5a08e77402420ff7e471bd38cf5ce354a104a194", + "witness": [ + "01", + "9dcf97a184f32623d11a73124ceb99a5709b083721e878a16d78f596718ba7b2", + "d050929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0", + "50616e6e6578" + ], + "max_cost": 10000000, + "expect": { + "error": "bad_witness" + } + }, + { + "name": "annex_tag_in_first_element_is_the_solution", + "script_pubkey": "5120864ac98761331f672c01124a5a08e77402420ff7e471bd38cf5ce354a104a194", + "witness": [ + "50", + "01", + "9dcf97a184f32623d11a73124ceb99a5709b083721e878a16d78f596718ba7b2", + "d050929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0" + ], + "max_cost": 10000000, + "expect": { + "error": "bad_condition_list" + } + }, + { + "name": "leaf_script_0_bytes", + "script_pubkey": "5120883bac9b380b0c56e5822efca56dc752644d90f27a45f38f3ad06a5fb5ae716d", + "witness": [ + "ffff33ff8203e88080", + "01", + "", + "d150929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0" + ], + "max_cost": 10000000, + "expect": { + "error": "bad_witness" + } + }, + { + "name": "leaf_script_31_bytes", + "script_pubkey": "5120b9f53f317b67e2ac607cfc747ceebe1b4ed578a006e95d0674f08ba6e796ff09", + "witness": [ + "ffff33ff8203e88080", + "01", + "11111111111111111111111111111111111111111111111111111111111111", + "d150929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0" + ], + "max_cost": 10000000, + "expect": { + "error": "bad_witness" + } + }, + { + "name": "leaf_script_33_bytes", + "script_pubkey": "5120f84085facb9c27febf2bd88a050f937899e24782caaf832b93354fc4279bd4fc", + "witness": [ + "ffff33ff8203e88080", + "01", + "111111111111111111111111111111111111111111111111111111111111111111", + "d050929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0" + ], + "max_cost": 10000000, + "expect": { + "error": "bad_witness" + } + }, + { + "name": "program_empty_element", + "script_pubkey": "5120864ac98761331f672c01124a5a08e77402420ff7e471bd38cf5ce354a104a194", + "witness": [ + "ffff33ff8203e88080", + "", + "9dcf97a184f32623d11a73124ceb99a5709b083721e878a16d78f596718ba7b2", + "d050929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0" + ], + "max_cost": 10000000, + "expect": { + "error": "bad_encoding" + } + }, + { + "name": "program_trailing_byte", + "script_pubkey": "5120864ac98761331f672c01124a5a08e77402420ff7e471bd38cf5ce354a104a194", + "witness": [ + "ffff33ff8203e88080", + "0180", + "9dcf97a184f32623d11a73124ceb99a5709b083721e878a16d78f596718ba7b2", + "d050929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0" + ], + "max_cost": 10000000, + "expect": { + "error": "bad_encoding" + } + }, + { + "name": "program_non_minimal_atom", + "script_pubkey": "5120864ac98761331f672c01124a5a08e77402420ff7e471bd38cf5ce354a104a194", + "witness": [ + "ffff33ff8203e88080", + "c00101", + "9dcf97a184f32623d11a73124ceb99a5709b083721e878a16d78f596718ba7b2", + "d050929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0" + ], + "max_cost": 10000000, + "expect": { + "error": "bad_encoding" + } + }, + { + "name": "program_truncated", + "script_pubkey": "5120864ac98761331f672c01124a5a08e77402420ff7e471bd38cf5ce354a104a194", + "witness": [ + "ffff33ff8203e88080", + "ff01", + "9dcf97a184f32623d11a73124ceb99a5709b083721e878a16d78f596718ba7b2", + "d050929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0" + ], + "max_cost": 10000000, + "expect": { + "error": "bad_encoding" + } + }, + { + "name": "leaf_mismatch", + "script_pubkey": "5120864ac98761331f672c01124a5a08e77402420ff7e471bd38cf5ce354a104a194", + "witness": [ + "ffff33ff8203e88080", + "02", + "9dcf97a184f32623d11a73124ceb99a5709b083721e878a16d78f596718ba7b2", + "d050929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0" + ], + "max_cost": 10000000, + "expect": { + "error": "leaf_mismatch" + } + }, + { + "name": "leaf_mismatch_wins_over_bad_solution", + "script_pubkey": "5120864ac98761331f672c01124a5a08e77402420ff7e471bd38cf5ce354a104a194", + "witness": [ + "", + "02", + "9dcf97a184f32623d11a73124ceb99a5709b083721e878a16d78f596718ba7b2", + "d050929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0" + ], + "max_cost": 10000000, + "expect": { + "error": "leaf_mismatch" + } + }, + { + "name": "leaf_mismatch_wins_over_vm_error", + "script_pubkey": "5120a564a6c4890e6e15ee033531cda4958175e7c752a3583877c561a81c5c0632c8", + "witness": [ + "ffff33ff8203e88080", + "01", + "044ebff3ad6d351856fd37d38c599ad0e416aa8a22621d8c13c27e24561f7f77", + "d150929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0" + ], + "max_cost": 10000000, + "expect": { + "error": "leaf_mismatch" + } + }, + { + "name": "solution_empty_element", + "script_pubkey": "5120864ac98761331f672c01124a5a08e77402420ff7e471bd38cf5ce354a104a194", + "witness": [ + "", + "01", + "9dcf97a184f32623d11a73124ceb99a5709b083721e878a16d78f596718ba7b2", + "d050929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0" + ], + "max_cost": 10000000, + "expect": { + "error": "bad_encoding" + } + }, + { + "name": "solution_trailing_byte", + "script_pubkey": "5120864ac98761331f672c01124a5a08e77402420ff7e471bd38cf5ce354a104a194", + "witness": [ + "ffff33ff8203e8808080", + "01", + "9dcf97a184f32623d11a73124ceb99a5709b083721e878a16d78f596718ba7b2", + "d050929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0" + ], + "max_cost": 10000000, + "expect": { + "error": "bad_encoding" + } + }, + { + "name": "solution_nil_is_one_byte", + "script_pubkey": "512019a1711d0c402084f7e8814adda58a2c37549f8345d69376de4029af191c916c", + "witness": [ + "80", + "ff0180", + "ba4484b961b7a2369d948d06c55b64bdbfaffb326bc13b490ab1215dd33d8d46", + "d050929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0" + ], + "max_cost": 10000000, + "expect": { + "conditions": [], + "tapleaf": "2b270110b679efa9f8555b942c8d83a6b80303ec3dee632075600e54947b9a25", + "merkle_root": "2b270110b679efa9f8555b942c8d83a6b80303ec3dee632075600e54947b9a25", + "internal_key": "50929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0", + "cost": 20 + } + }, + { + "name": "vm_error_wins_over_unasserted_annex", + "script_pubkey": "5120a564a6c4890e6e15ee033531cda4958175e7c752a3583877c561a81c5c0632c8", + "witness": [ + "80", + "ff0880", + "044ebff3ad6d351856fd37d38c599ad0e416aa8a22621d8c13c27e24561f7f77", + "d150929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0", + "50616e6e6578" + ], + "max_cost": 10000000, + "expect": { + "error": "user_raise" + } + }, + { + "name": "budget_below_evaluation", + "script_pubkey": "5120864ac98761331f672c01124a5a08e77402420ff7e471bd38cf5ce354a104a194", + "witness": [ + "ffff33ff8203e88080", + "01", + "9dcf97a184f32623d11a73124ceb99a5709b083721e878a16d78f596718ba7b2", + "d050929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0" + ], + "max_cost": 1, + "expect": { + "error": "cost_exceeded" + } + }, + { + "name": "budget_covers_evaluation_not_conditions", + "script_pubkey": "5120864ac98761331f672c01124a5a08e77402420ff7e471bd38cf5ce354a104a194", + "witness": [ + "ffff33ff8203e88080", + "01", + "9dcf97a184f32623d11a73124ceb99a5709b083721e878a16d78f596718ba7b2", + "d050929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0" + ], + "max_cost": 243, + "expect": { + "error": "cost_exceeded" + } + }, + { + "name": "budget_exactly_the_total", + "script_pubkey": "5120864ac98761331f672c01124a5a08e77402420ff7e471bd38cf5ce354a104a194", + "witness": [ + "ffff33ff8203e88080", + "01", + "9dcf97a184f32623d11a73124ceb99a5709b083721e878a16d78f596718ba7b2", + "d050929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0" + ], + "max_cost": 244, + "expect": { + "conditions": [ + { + "opcode": 51, + "amount": 1000 + } + ], + "tapleaf": "dde54461ef9453a9d235b60142c77f6680d0243ec4a02d206750059e8ea08b95", + "merkle_root": "dde54461ef9453a9d235b60142c77f6680d0243ec4a02d206750059e8ea08b95", + "internal_key": "50929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0", + "cost": 244 + } + }, + { + "name": "non_list_result", + "script_pubkey": "512013ab23dbb277c68d5172950ff252745590870269f7e31966439af07cc94a6628", + "witness": [ + "80", + "ff0101", + "69ae360134b1fae04326e5546f25dc794a19192a1f22a44a46d038e7f0d1ecbb", + "d150929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0" + ], + "max_cost": 10000000, + "expect": { + "error": "bad_condition_list" + } + }, + { + "name": "parse_error_wins_over_unasserted_annex", + "script_pubkey": "512013ab23dbb277c68d5172950ff252745590870269f7e31966439af07cc94a6628", + "witness": [ + "80", + "ff0101", + "69ae360134b1fae04326e5546f25dc794a19192a1f22a44a46d038e7f0d1ecbb", + "d150929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0", + "50616e6e6578" + ], + "max_cost": 10000000, + "expect": { + "error": "bad_condition_list" + } + } + ] +} From 43bcbd225b0224b368c075b3fee293f3bd13b10a Mon Sep 17 00:00:00 2001 From: Evan Date: Sun, 6 Sep 2026 13:20:14 -0700 Subject: [PATCH 07/17] tests: the witness layer against its oracles The commitment scheme's hashing has real oracles and this file uses them. The official BIP341 wallet vectors give every leaf's control block, leaf hash, merkle root, and scriptPubKey under leaf versions 0xc0 and 0xfa: ControlBlock reads all twelve to the published identity, passes the base consensus check against the published output, and rejects a flipped output byte, a flipped parity bit, and a lengthened leaf script. The vendored Bitcoin Core framework is the oracle for the tagged hash over every tag the package uses, the leaf hash under any leaf version, and the annex digest's serialization, including the three-byte compact size a bound-sized annex needs. The tree hash is checked against the VM's sha256tree operator, which the differential harness pins to the consensus wheel. The digest-domain table of SPEC.md section 2.4 is recomputed from the tag strings: every first byte, none 0x01 or 0x02, and the table is exactly the set of tags the package hashes under, so a new tag fails here until the spec's table gains its row. Found the table's BIP340/challenge row wrong, fixed in the spec commit before this. The spend entry's invariants: under the anyone-can-spend program an annex passes the input stages exactly when the solution asserts its hash, the element bound is exact at MAX_WITNESS_ELEMENT_SIZE, the identity is the leaf hash and the path fold whatever the path, the annex split follows BIP341 on its edge cases, and a key-path spend or a foreign leaf version raises BaseConsensusError. --- python/tests/test_spend.py | 375 +++++++++++++++++++++++++++++++++++++ 1 file changed, 375 insertions(+) create mode 100644 python/tests/test_spend.py diff --git a/python/tests/test_spend.py b/python/tests/test_spend.py new file mode 100644 index 0000000..dcd4141 --- /dev/null +++ b/python/tests/test_spend.py @@ -0,0 +1,375 @@ +"""The witness layer against its oracles and its invariants. + +The commitment scheme's hashing has real oracles: the official BIP341 +wallet vectors for the leaf hash, the path fold, and the output key +under arbitrary leaf versions, and the vendored Bitcoin Core test +framework for the tagged hash and the annex digest's serialization. +The tree hash is checked against the VM's own sha256tree operator, +which the differential harness pins to the consensus wheel. The +digest-domain table of the spec is recomputed from the tag strings +the package hashes under. The spend entry's invariants cover what no +vector enumerates: any well-formed spend gains an annex only under +its assert, the element bound is exact, and the identity read is a +pure function of the control block and leaf. +""" + +import hashlib +import json +import sys +from pathlib import Path + +import pytest +from hypothesis import given, settings +from hypothesis import strategies as st + +REPO_ROOT = Path(__file__).resolve().parent.parent.parent +sys.path.insert(0, str(REPO_ROOT / "python")) +sys.path.insert(0, str(REPO_ROOT / "tools" / "oracle" / "bitcoincore")) + +from bitlisp import ( # noqa: E402 + NIL, + BaseConsensusError, + BitLispError, + TxInput, + evaluate_spend, + serialize, +) +from bitlisp.commitment import ( # noqa: E402 + BITLISP_LEAF_VERSION, + ControlBlock, + merkle_root, + sha_annex, + tagged_hash, + tapleaf_hash, + taproot_script_pubkey, + tree_hash, +) +from bitlisp.operators import op_sha256tree # noqa: E402 +from bitlisp.secp256k1 import taproot_output_point # noqa: E402 +from bitlisp.spend import MAX_WITNESS_ELEMENT_SIZE, split_annex # noqa: E402 +from support import NUMS # noqa: E402 +from test_framework.key import TaggedHash # noqa: E402 +from test_framework.messages import ser_string # noqa: E402 + +EXAMPLES = settings(max_examples=50, deadline=None) +VECTORS_JSON = ( + REPO_ROOT / "vectors" / "upstream" / "bip341" / "wallet-test-vectors.json" +) + + +# --- the official BIP341 vectors: leaf hash, path fold, output key ---------- + + +def _leaves(tree): + """The leaves of a wallet-vector script tree in id order.""" + if isinstance(tree, dict): + return [tree] + return [leaf for branch in tree for leaf in _leaves(branch)] + + +def bip341_leaf_cases(): + with open(VECTORS_JSON) as fh: + entries = json.load(fh)["scriptPubKey"] + cases = [] + for n, entry in enumerate(entries): + tree = entry["given"]["scriptTree"] + if tree is None: + continue + leaves = sorted(_leaves(tree), key=lambda leaf: leaf["id"]) + blocks = entry["expected"]["scriptPathControlBlocks"] + for leaf, block in zip(leaves, blocks, strict=True): + cases.append( + pytest.param( + bytes.fromhex(entry["given"]["internalPubkey"]), + leaf["leafVersion"], + bytes.fromhex(leaf["script"]), + bytes.fromhex(block), + bytes.fromhex(entry["intermediary"]["leafHashes"][leaf["id"]]), + bytes.fromhex(entry["intermediary"]["merkleRoot"]), + bytes.fromhex(entry["expected"]["scriptPubKey"]), + id=f"bip341_{n}_leaf_{leaf['id']}", + ) + ) + assert len(cases) == 12 + return cases + + +@pytest.mark.parametrize( + "key,version,script,block,leaf_hash,root,spk", bip341_leaf_cases() +) +def test_official_control_blocks_read_to_the_published_identity( + key, version, script, block, leaf_hash, root, spk +): + control = ControlBlock.parse(block) + assert control.leaf_version == version + assert control.internal_key == key + assert control.identity(script) == (leaf_hash, root) + assert control.check(script, spk) == (leaf_hash, root) + assert taproot_script_pubkey(key, root) == spk + + +@pytest.mark.parametrize( + "key,version,script,block,leaf_hash,root,spk", bip341_leaf_cases() +) +def test_official_control_blocks_reject_a_foreign_output( + key, version, script, block, leaf_hash, root, spk +): + control = ControlBlock.parse(block) + other = spk[:-1] + bytes([spk[-1] ^ 1]) + with pytest.raises(BaseConsensusError, match="not the taproot output"): + control.check(script, other) + flipped = bytes([block[0] ^ 1]) + block[1:] + with pytest.raises(BaseConsensusError, match="parity"): + ControlBlock.parse(flipped).check(script, spk) + with pytest.raises(BaseConsensusError, match="not the taproot output"): + control.check(script + b"\x00", spk) + + +def test_official_key_path_outputs(): + with open(VECTORS_JSON) as fh: + entries = json.load(fh)["scriptPubKey"] + checked = 0 + for entry in entries: + if entry["given"]["scriptTree"] is None: + key = bytes.fromhex(entry["given"]["internalPubkey"]) + assert ( + taproot_script_pubkey(key, b"").hex() + == entry["expected"]["scriptPubKey"] + ) + checked += 1 + assert checked == 1 + + +@pytest.mark.parametrize("size", [0, 32, 34, 66, 33 + 32 * 129]) +def test_control_block_lengths_rejected(size): + with pytest.raises(BaseConsensusError, match="33 plus 32m"): + ControlBlock.parse(b"\x00" * size) + + +def test_control_block_length_bounds_accepted(): + ControlBlock.parse(bytes([BITLISP_LEAF_VERSION]) + NUMS) + ControlBlock.parse(bytes([BITLISP_LEAF_VERSION]) + NUMS + b"\x00" * (32 * 128)) + + +def test_off_curve_internal_key_rejected(): + control = ControlBlock.parse(bytes([BITLISP_LEAF_VERSION]) + b"\xff" * 32) + with pytest.raises(BaseConsensusError, match="no curve point"): + control.check(b"\x00" * 32, b"\x51\x20" + b"\x00" * 32) + + +# --- the Core framework: tagged hash and annex serialization --------------- + +tags = st.sampled_from(("TapLeaf", "TapBranch", "TapTweak", "BIP0340/challenge")) +payloads = st.binary(max_size=200) + + +@EXAMPLES +@given(tags, payloads) +def test_tagged_hash_matches_core(tag, data): + assert tagged_hash(tag, data) == TaggedHash(tag, data) + + +@EXAMPLES +@given(st.integers(0, 0xFF), st.binary(max_size=300)) +def test_tapleaf_hash_matches_core_under_any_version(version, script): + version &= 0xFE + expected = TaggedHash("TapLeaf", bytes([version]) + ser_string(script)) + assert tapleaf_hash(version, script) == expected + + +@EXAMPLES +@given(st.binary(min_size=0, max_size=300)) +def test_sha_annex_matches_core_serialization(annex): + assert sha_annex(annex) == hashlib.sha256(ser_string(annex)).digest() + + +def test_sha_annex_covers_a_bound_sized_annex(): + annex = b"\x50" + b"\x00" * (MAX_WITNESS_ELEMENT_SIZE - 1) + # The compact-size prefix turns three bytes wide at 253. + assert sha_annex(annex) == hashlib.sha256(ser_string(annex)).digest() + + +# --- the tree hash against the VM operator --------------------------------- + +atoms = st.binary(max_size=8) +nodes = st.recursive( + atoms, lambda children: st.tuples(children, children), max_leaves=12 +) + + +@EXAMPLES +@given(nodes) +def test_tree_hash_matches_the_operator(node): + assert tree_hash(node) == op_sha256tree([node], lambda amount: None) + + +def test_tree_hash_of_named_programs(): + # The two programs the spec names, and the leaf script they give. + assert tree_hash(b"\x01") == hashlib.sha256(b"\x01\x01").digest() + assert tree_hash(NIL) == hashlib.sha256(b"\x01").digest() + + +# --- the digest-domain table ----------------------------------------------- + +# Every tag a BitLisp validator hashes under, and the first byte of +# each tag's digest, as the spec's table states them. +DIGEST_DOMAIN_TABLE = { + "TapLeaf": 0xAE, + "TapBranch": 0x19, + "TapTweak": 0xE8, + "BIP0340/challenge": 0x7B, + "BitLisp/sig/my_txid": 0x54, + "BitLisp/sig/my_scriptpubkey": 0xE3, + "BitLisp/sig/my_amount": 0xDF, + "BitLisp/sig/my_scriptpubkey_amount": 0xEC, + "BitLisp/sig/my_txid_amount": 0xFF, + "BitLisp/sig/my_txid_scriptpubkey": 0xE5, + "BitLisp/sig/raw": 0x56, + "BitLisp/sig/my_outpoint": 0xDA, +} + + +def test_digest_domain_table_first_bytes(): + for tag, first in DIGEST_DOMAIN_TABLE.items(): + assert hashlib.sha256(tag.encode("ascii")).digest()[0] == first, tag + # No tagged-hash preimage begins like a tree-hash preimage. + assert not {0x01, 0x02} & set(DIGEST_DOMAIN_TABLE.values()) + + +def test_digest_domain_table_is_every_tag_the_package_hashes_under(): + from bitlisp.conditions import SIG_BINDINGS + + package = REPO_ROOT / "python" / "bitlisp" + sig_tags = {binding[1] for binding in SIG_BINDINGS.values()} + literal_tags = set() + for path in package.glob("*.py"): + text = path.read_text() + for tag in ("TapLeaf", "TapBranch", "TapTweak", "BIP0340/challenge"): + if f'"{tag}"' in text or f'b"{tag}"' in text: + literal_tags.add(tag) + assert sig_tags | literal_tags == set(DIGEST_DOMAIN_TABLE) + + +# --- the spend entry's invariants ------------------------------------------ + + +def _clist(*items): + node = NIL + for item in reversed(items): + node = (item, node) + return node + + +def _spend(program, solution, annex=None, path=b"", max_cost=10_000_000): + """Evaluates a program over a solution as a single-leaf spend under + NUMS, returning (cost, input) or the error code.""" + leaf = tree_hash(program) + root = merkle_root(tapleaf_hash(BITLISP_LEAF_VERSION, leaf), path) + x, y = taproot_output_point(NUMS, root) + block = bytes([BITLISP_LEAF_VERSION | (y & 1)]) + NUMS + path + witness = [serialize(solution), serialize(program), leaf, block] + if annex is not None: + witness.append(annex) + tx_input = TxInput(b"\x00" * 32, 0, taproot_script_pubkey(NUMS, root), 1, 0) + try: + return evaluate_spend(tx_input, witness, max_cost) + except BitLispError as exc: + return exc.code + + +def _annex_assert(annex_hash): + return _clist(b"\x39", annex_hash) + + +amount_asserts = st.integers(0, 3).map( + lambda n: _clist(b"\x33", bytes([n]) if n else NIL) +) +solutions = st.lists(amount_asserts, max_size=3).map(lambda conds: _clist(*conds)) +annexes = st.one_of(st.none(), st.binary(max_size=40).map(lambda tail: b"\x50" + tail)) + + +@EXAMPLES +@given(solutions, annexes, st.booleans()) +def test_annex_admitted_exactly_under_its_assert(solution, annex, asserted): + """Under the anyone-can-spend program, a spend with an annex passes + the input stages exactly when its solution asserts that annex's + hash, and a spend without one always does.""" + if asserted and annex is not None: + solution = (_annex_assert(sha_annex(annex)), solution) + outcome = _spend(b"\x01", solution, annex) + if annex is None or asserted: + cost, spent = outcome + assert spent.annex_hash == (None if annex is None else sha_annex(annex)) + else: + assert outcome == "unasserted_annex" + + +@EXAMPLES +@given(st.integers(-3, 3)) +def test_element_bound_is_exact(delta): + """A solution element of exactly MAX_WITNESS_ELEMENT_SIZE bytes + passes stage 1 and one more byte fails it, under the program that + ignores its solution.""" + size = MAX_WITNESS_ELEMENT_SIZE + delta + atom = next( + b"\x00" * n + for n in range(size - 3, size + 1) + if len(serialize(b"\x00" * n)) == size + ) + outcome = _spend((b"\x01", NIL), atom) + if delta <= 0: + assert outcome[1].conditions == () + else: + assert outcome == "bad_witness" + + +@EXAMPLES +@given(st.lists(st.binary(min_size=32, max_size=32), max_size=4)) +def test_identity_is_read_from_the_control_block(siblings): + """The identity the spend carries is the leaf hash of the revealed + leaf script and the fold of the control block's path, whatever + the path.""" + path = b"".join(siblings) + cost, spent = _spend((b"\x01", NIL), NIL, path=path) + leaf = tree_hash((b"\x01", NIL)) + tapleaf = tapleaf_hash(BITLISP_LEAF_VERSION, leaf) + assert spent.tapleaf == tapleaf + assert spent.merkle_root == merkle_root(tapleaf, path) + assert spent.internal_key == NUMS + assert (spent.merkle_root == tapleaf) == (path == b"") + + +def test_split_annex_follows_bip341(): + assert split_annex([b"\x50"]) == ([b"\x50"], None) + assert split_annex([b"\x01", b"\x50"]) == ([b"\x01"], b"\x50") + assert split_annex([b"\x50", b"\x01"]) == ([b"\x50", b"\x01"], None) + assert split_annex([b"\x01", b""]) == ([b"\x01", b""], None) + assert split_annex([]) == ([], None) + + +def test_key_path_and_foreign_leaf_versions_are_outside_bitlisp(): + leaf = tree_hash(b"\x01") + root = merkle_root(tapleaf_hash(0xC0, leaf), b"") + x, y = taproot_output_point(NUMS, root) + block = bytes([0xC0 | (y & 1)]) + NUMS + tx_input = TxInput(b"\x00" * 32, 0, taproot_script_pubkey(NUMS, root), 1, 0) + with pytest.raises(BaseConsensusError, match="leaf version"): + evaluate_spend(tx_input, [b"\x80", b"\x01", leaf, block], 1000) + with pytest.raises(BaseConsensusError, match="not a script-path spend"): + evaluate_spend(tx_input, [b"\x00" * 64], 1000) + with pytest.raises(ValueError, match="already carries"): + evaluate_spend( + TxInput( + b"\x00" * 32, + 0, + b"\x51", + 1, + 0, + conditions=(), + tapleaf=leaf, + merkle_root=leaf, + internal_key=NUMS, + ), + [b"\x80", b"\x01", leaf, block], + 1000, + ) From a177b7624248bfe12819a273b75b1000900e6bfe Mon Sep 17 00:00:00 2001 From: Evan Date: Sun, 6 Sep 2026 13:21:44 -0700 Subject: [PATCH 08/17] tools: bitlisp-commit, what an output commits to The commitment-hash utility queued 2026-08-14 and moved to this PR when the scheme fixed its output. From a program, as text or as serialized hex, it prints the leaf script (the tree hash), the tapleaf hash under BitLisp's leaf version, the merkle root, the internal key, the control block a spend of the leaf carries, and the taproot scriptPubKey. --sibling names the path elements leaf upward for a leaf that shares its tree, and --internal-key replaces the default, the BIP341 nothing-up-my-sleeve point, so the default output has no key path. The control block is the piece a spender needs and the one no other tool produces. Tests pin its output against the spend suite's identity vectors, which were cross-checked against the Bitcoin Core tagged hash, and its exit 2 paths: a program that does not parse or decode, a sibling that is not hex, a key of the wrong width, a key that does not lift. The eighth console script, listed with the others. --- CLAUDE.md | 1 + README.md | 7 +- pyproject.toml | 1 + python/bitlisp_tools/cli.py | 118 ++++++++++++++++++++++++++++++- python/tests/test_convert_cli.py | 74 ++++++++++++++++++- 5 files changed, 194 insertions(+), 7 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 012ede6..f33a3aa 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -153,6 +153,7 @@ python3 -m venv .venv && .venv/bin/pip install -e ".[dev,oracles]" .venv/bin/bitlisp-asm [text] # text to serialized bytecode hex .venv/bin/bitlisp-disasm [hex] # serialized bytecode hex to text .venv/bin/bitlisp-compile [source] # v0 language source to bytecode hex +.venv/bin/bitlisp-commit [program] # leaf script, tapleaf, merkle root, control block, scriptPubKey .venv/bin/python tools/run_vectors.py # full vector corpus .venv/bin/python tools/diff_clvm.py --count 10000 --seed 1 # diff harness .venv/bin/python tools/mutate.py --tests # mutation pass, survivors need triage diff --git a/README.md b/README.md index e666194..3a35010 100644 --- a/README.md +++ b/README.md @@ -44,7 +44,7 @@ ci/lint/lint.sh ## Using the tools -The editable install adds seven console scripts: +The editable install adds eight console scripts: ``` .venv/bin/bitlisp [tx.json] # REPL with stepping debugger @@ -54,11 +54,14 @@ The editable install adds seven console scripts: .venv/bin/bitlisp-compile [source] # v0 language source to bytecode hex .venv/bin/bitlisp-curry [hex] --arg # fix values into a program .venv/bin/bitlisp-uncurry [hex] # split a curried program back out +.venv/bin/bitlisp-commit [program] [--sibling ] # leaf, root, control block, scriptPubKey ``` `bitlisp-run` reports the verdict, the emitted conditions, and the cost for one spend, exiting 0 on a valid spend, 1 on an invalid -one, and 2 on input that could not be used. The converters read +one, and 2 on input that could not be used. `bitlisp-commit` prints +what an output committing to a program commits to, and the control +block a spend of it carries. The converters read stdin when no argument is given and compose in pipes. The REPL loads the same transaction context, keeps a constants scratch space, and drives the debugger with `step`, `next`, `cont`, and diff --git a/pyproject.toml b/pyproject.toml index 338e777..bd8d431 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -37,6 +37,7 @@ bitlisp-disasm = "bitlisp_tools.cli:disasm_main" bitlisp-compile = "bitlisp_tools.cli:compile_main" bitlisp-curry = "bitlisp_tools.cli:curry_main" bitlisp-uncurry = "bitlisp_tools.cli:uncurry_main" +bitlisp-commit = "bitlisp_tools.cli:commit_main" [tool.setuptools] package-dir = {"" = "python"} diff --git a/python/bitlisp_tools/cli.py b/python/bitlisp_tools/cli.py index 701a2bc..8ae2470 100644 --- a/python/bitlisp_tools/cli.py +++ b/python/bitlisp_tools/cli.py @@ -1,5 +1,6 @@ """The one-shot command surface: bitlisp-run, bitlisp-asm, -bitlisp-disasm, bitlisp-compile, bitlisp-curry, bitlisp-uncurry. +bitlisp-disasm, bitlisp-compile, bitlisp-curry, bitlisp-uncurry, +bitlisp-commit. Each command is a thin main over the tools library. bitlisp-run runs one spend and reports the verdict. bitlisp-asm assembles a text @@ -8,7 +9,9 @@ program to serialized bytecode hex. bitlisp-curry fixes argument values into a program and bitlisp-uncurry splits them back out. The converters and bitlisp-curry take -T to print the program's tree -hash instead of their usual output. +hash instead of their usual output. bitlisp-commit prints what an +output committing to a program commits to: the leaf script, the +leaf hash, the merkle root, the control block, and the scriptPubKey. """ import argparse @@ -18,8 +21,15 @@ import sys from bitlisp import BitLispError, deserialize, serialize +from bitlisp.commitment import ( + BITLISP_LEAF_VERSION, + merkle_root, + tapleaf_hash, + tree_hash, +) +from bitlisp.secp256k1 import taproot_output_point -from .compiler import CompileError, compile_program, symbols_to_json, tree_hash +from .compiler import CompileError, compile_program, symbols_to_json from .curry import curry, uncurry from .printer import disassemble from .reader import ParseError, assemble @@ -206,6 +216,108 @@ """ +_COMMIT_DOC = """Print what an output committing to a program commits to. + +Takes a program as text s-expression syntax, or as serialized hex +with --hex, and prints the leaf script (the program's tree hash), +the tapleaf hash under BitLisp's leaf version, the merkle root of +the leaf's position in its tree, the internal key, the control +block a spend of the leaf carries, and the taproot scriptPubKey of +the output. The leaf sits alone in its tree unless --sibling names +the 32-byte hashes beside it, leaf upward, in which case the merkle +root and the control block carry that path. The internal key is the +BIP341 nothing-up-my-sleeve point unless --internal-key names one, +so the default output has no key path. + +The program argument names a file when one exists at that path and +reads as the literal otherwise, or comes from stdin when omitted. + +Exit status 0 on success, 2 when the program does not parse, a hash +or key is not 32 bytes of hex, the internal key does not lift to a +curve point, or the file does not open. + +Usage: + bitlisp-compile vault.bl | bitlisp-commit --hex + bitlisp-commit "(q (51 0x51 1000))" --sibling --sibling +""" + +# The BIP341 nothing-up-my-sleeve point: an output whose internal +# key is this point has no key path anyone can use. +_NUMS_POINT = "50929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0" + + +def _hex32(text, what): + try: + value = bytes.fromhex(text) + except ValueError: + raise ValueError(f"{what} is not hex: {text!r}") from None + if len(value) != 32: + raise ValueError(f"{what} must be 32 bytes, got {len(value)}") + return value + + +def commit_main(argv=None): + parser = argparse.ArgumentParser( + prog="bitlisp-commit", + description=_COMMIT_DOC, + formatter_class=argparse.RawDescriptionHelpFormatter, + ) + parser.add_argument( + "program", + nargs="?", + help="file path, or the literal program (default stdin)", + ) + parser.add_argument( + "--hex", action="store_true", help="read the program as serialized hex" + ) + parser.add_argument( + "-k", + "--internal-key", + default=_NUMS_POINT, + metavar="HEX", + help="the 32-byte x-only internal key (default the BIP341 NUMS point)", + ) + parser.add_argument( + "-s", + "--sibling", + action="append", + default=[], + metavar="HEX", + help="a 32-byte merkle path element, repeatable, leaf upward", + ) + args = parser.parse_args(argv) + try: + program = _node(_input_text(args.program), args.hex) + internal_key = _hex32(args.internal_key, "internal key") + path = b"".join(_hex32(sibling, "sibling") for sibling in args.sibling) + leaf_script = tree_hash(program) + tapleaf = tapleaf_hash(BITLISP_LEAF_VERSION, leaf_script) + root = merkle_root(tapleaf, path) + output = taproot_output_point(internal_key, root) + if output is None: + raise ValueError("the internal key does not lift to a curve point") + except BitLispError as exc: + print(f"error: {exc.code}: {exc}", file=sys.stderr) + return 2 + except (ParseError, OSError, ValueError) as exc: + print(f"error: {exc}", file=sys.stderr) + return 2 + x, y = output + control_block = bytes([BITLISP_LEAF_VERSION | (y & 1)]) + internal_key + path + lines = ( + ("leaf script", leaf_script), + ("tapleaf", tapleaf), + ("merkle root", root), + ("internal key", internal_key), + ("control block", control_block), + ("scriptPubKey", b"\x51\x20" + x.to_bytes(32, "big")), + ) + with _pipe_shield(): + for label, value in lines: + print(f"{label + ':':<15}{value.hex()}") + return 0 + + def _path_or_code(arg): """The argument is the file's content when one exists at that path, and the literal otherwise. Existence alone selects file diff --git a/python/tests/test_convert_cli.py b/python/tests/test_convert_cli.py index ee64125..04b8bef 100644 --- a/python/tests/test_convert_cli.py +++ b/python/tests/test_convert_cli.py @@ -1,6 +1,6 @@ """The one-shot command tests: bitlisp-asm, bitlisp-disasm, -bitlisp-compile, bitlisp-curry, bitlisp-uncurry, the tree-hash -flag, and the corpus pin.""" +bitlisp-compile, bitlisp-curry, bitlisp-uncurry, bitlisp-commit, the +tree-hash flag, and the corpus pin.""" import io import json @@ -177,6 +177,76 @@ def test_console_scripts_resolve(): assert entry.load() is cli.asm_main (entry,) = metadata.entry_points(group="console_scripts", name="bitlisp-disasm") assert entry.load() is cli.disasm_main + (entry,) = metadata.entry_points(group="console_scripts", name="bitlisp-commit") + assert entry.load() is cli.commit_main + + +# bitlisp-commit: its output against the spend suite's identity cases, +# which were cross-checked against the Bitcoin Core tagged hash. + + +def _identity_case(name): + path = REPO_ROOT / "vectors" / "spend" / "identity.json" + (case,) = [c for c in json.loads(path.read_text())["cases"] if c["name"] == name] + return case + + +def _commit_lines(out): + return dict(line.split(":", 1) for line in out.rstrip("\n").split("\n")) + + +def test_commit_single_leaf_matches_the_identity_vector(capsys): + case = _identity_case("single_leaf") + solution, program, leaf, block = case["witness"] + assert cli.commit_main([program, "--hex"]) == 0 + lines = {k: v.strip() for k, v in _commit_lines(capsys.readouterr().out).items()} + assert lines == { + "leaf script": leaf, + "tapleaf": case["expect"]["tapleaf"], + "merkle root": case["expect"]["merkle_root"], + "internal key": case["expect"]["internal_key"], + "control block": block, + "scriptPubKey": case["script_pubkey"], + } + + +def test_commit_with_path_and_key_matches_the_identity_vector(capsys): + case = _identity_case("internal_key_generator_with_path") + solution, program, leaf, block = case["witness"] + siblings = [block[66 + 64 * i : 66 + 64 * (i + 1)] for i in range(1)] + argv = [program, "--hex", "-k", case["expect"]["internal_key"]] + for sibling in siblings: + argv += ["-s", sibling] + assert cli.commit_main(argv) == 0 + lines = {k: v.strip() for k, v in _commit_lines(capsys.readouterr().out).items()} + assert lines["merkle root"] == case["expect"]["merkle_root"] + assert lines["control block"] == block + assert lines["scriptPubKey"] == case["script_pubkey"] + + +def test_commit_text_program_and_stdin(capsys, monkeypatch): + # The atom 1 spelled as text and as hex give one leaf script. + assert cli.commit_main(["1"]) == 0 + from_text = capsys.readouterr().out + monkeypatch.setattr(sys, "stdin", io.StringIO("01\n")) + assert cli.commit_main(["--hex"]) == 0 + assert capsys.readouterr().out == from_text + assert ( + _commit_lines(from_text)["leaf script"].strip() == cli.tree_hash(b"\x01").hex() + ) + + +def test_commit_rejects_bad_inputs(capsys): + assert cli.commit_main(["(q . 1"]) == 2 + assert capsys.readouterr().err.startswith("error: ") + assert cli.commit_main(["1", "-k", "ff" * 32]) == 2 + assert "does not lift" in capsys.readouterr().err + assert cli.commit_main(["1", "-k", "ab" * 31]) == 2 + assert "32 bytes" in capsys.readouterr().err + assert cli.commit_main(["1", "-s", "zz"]) == 2 + assert "not hex" in capsys.readouterr().err + assert cli.commit_main(["c00101", "--hex"]) == 2 + assert capsys.readouterr().err.startswith("error: bad_encoding: ") def test_asm_broken_pipe_keeps_exit_zero(tmp_path): From 9ba6c27d0e57cc6b28b736c57c33973799be756f Mon Sep 17 00:00:00 2001 From: Evan Date: Sun, 6 Sep 2026 13:23:16 -0700 Subject: [PATCH 09/17] docs: the witness layer recorded The commitment record gains a section for the reference witness layer: the three choices made in landing it (base consensus's checks run as a precondition outside the taxonomy, the annex rule run once per stage on two paths, the runner's witness form deferred to unit 9), and the two spec corrections the vectors and tests forced (the nil program, the challenge tag). Decision 3's owed vector is the test that recomputes the digest table, described where the vector was promised. The carried list loses the two items this PR delivered. The condition record's C25 row and decision 30 name the files their owed vectors landed in, the VM record's entry 7 the same for the disjointness pin. The glossary gains the control block, a term the spec used without a row. The REPL doc lists bitlisp-commit with the other one-shot commands and shows its output. --- docs/commitment-record.md | 48 +++++++++++++++++++++++++++++++-------- docs/condition-record.md | 8 ++++--- docs/glossary.md | 1 + docs/lang/repl.md | 33 +++++++++++++++++++++++---- docs/vm-record.md | 5 ++-- 5 files changed, 76 insertions(+), 19 deletions(-) diff --git a/docs/commitment-record.md b/docs/commitment-record.md index 7b72ccf..9d1709b 100644 --- a/docs/commitment-record.md +++ b/docs/commitment-record.md @@ -128,8 +128,14 @@ the trigger. table is exhaustive over those tags and gains a row with any new one, the check that keeps the argument true. TapSighash is base consensus's key-path digest, computed by no BitLisp rule, and - its first byte is `0xf4` regardless. The vector pinning the - table lands with the reference witness layer. + its first byte is `0xf4` regardless. The table is pinned by a + test that recomputes every row from the tag strings the + implementation hashes under and checks the set of rows is exactly + the set of tags in use (landed 2026-09-06 with the reference + witness layer). Writing that test found the challenge row wrong: + the table had named the tag `BIP340/challenge` with first byte + `0x07`, and BIP340 spells it `BIP0340/challenge`, first byte + `0x7b`. Corrected the same day, the argument unchanged. 4. **The witness is four elements, and an annex only under a self assert.** RATIFIED (decision by Evan, 2026-09-06, revising the @@ -312,11 +318,33 @@ the trigger. asset token study. - Relay policy for the leaf version: today's policy discourages unknown leaf versions, a deployment question for Phase 6. -- The commitment-hash utility: a command printing a leaf hash, a - merkle root, and a scriptPubKey from program sources, lands with - the reference witness layer now that the scheme fixes its output. -- Vectors owed to the reference witness layer: every stage 1 and 2 - failure mode including the element bound at and above 10,000 - bytes, the digest-domain table, the two programs spec section - 3.3 names, the atom `1` and nil, and the annex rule in both - directions with the ASSERT_MY_ANNEX cases. + +## 5. The reference witness layer + +Landed 2026-09-06, the PR after the scheme. `python/bitlisp/` +gained `commitment.py` (the tree hash, the tagged hashes, the +control block) and `spend.py` (the stages of spec section 4 for one +input), the vector corpus a `spend` suite, and the front end +`bitlisp-commit`, the commitment-hash utility queued 2026-08-14. +Three choices made there, none a change to the scheme: + +- Base consensus's control block checks are run by the reference + as a precondition and reported outside the error taxonomy + (`BaseConsensusError`), never as a code a vector could pin: the + spec says a spend failing them never reaches it, and a reference + that read the triple unchecked would call spends valid that base + consensus rejects. A vector whose witness fails them is + malformed. +- The annex admission rule is one function run twice on the + reference path, at stage 5 by the spend entry and first in + transaction validation, because the validation vectors and the + runner assemble transaction views without the spend entry and + the view's invariant must hold for them too. +- The witness form of `bitlisp-run` and the REPL is deferred to + unit 9's first PR, where the vault is the first consumer. + +Writing the vectors found spec section 3.3 wrong about the nil +program (its empty condition list is valid under CONDITIONS.md and +the corpus, so the nil leaf is spendable by anyone) and the digest +table wrong about the challenge tag (decision 3). Both corrected +in their own spec commits. diff --git a/docs/condition-record.md b/docs/condition-record.md index 4f30a9f..1bf23b7 100644 --- a/docs/condition-record.md +++ b/docs/condition-record.md @@ -39,7 +39,7 @@ Section 4 registers the rules that have no external reference at all. | C22 | signature-condition cost | 1,200,000 (AGG_SIG_COST) per occurrence in every regime, pricing one BLS pairing toward the bundle aggregate | 1,300,000 (CONDITION_SIG_ASSERT_COST), equal to the VM's SECP_VERIFY_COST, PROVISIONAL | Both layers of BitLisp price the same BIP340 verification, so the condition constant ties to the operator constant rather than to Chia's BLS figure: one Phase 4 measurement settles both, and a program can never buy the same verification cheaper in one layer than the other. Chia's magnitude corroborates the range, their pairing being work of the same order. Ratified 2026-08-09, decision 25. | `conditions/costs.json` signature cases | | C23 | execution-identity addressing | none: puzzle hash is both the coin's script commitment and the executing program, one field carries both meanings | the specifier table composes the executing leaf's tapleaf hash (bit 3) and the spending path's merkle root (bit 4) onto the prevout rows, commitment values 0 to 31, the mode packed as assurer times 32 plus requirer, both fields validator-filled from the control block. The pair itself is renamed ASSURE and REQUIRE (decision 27) | Taproot splits Chia's one identity into two, and the C9 mapping carried only the script commitment, so program-to-program trust had no faithful addressing field. Internal-key addressing declined as attacker-satisfiable (no possession proof in BIP341). Grafted-leaf and moved-root caveats recorded in decision 26 and in rule 3's author guidance. Ratified 2026-08-18, decision 26, landed 2026-08-20. | `validation/messages.json` identity cases, `conditions/messages.json` composed-mode cases | | C24 | the cheap identity assert | none: ASSERT_MY_PUZZLEHASH reads the one identity field, and no derive-versus-read split exists because a puzzle hash is a plain tree hash | ASSERT_MY_TAPTREE, a self assert over the control block's internal key and merkle root at the generic cost, the transaction view's identity widened to a triple. ASSERT_MY_TAPROOT, the derivation assert it subsumes, removed once the puzzle rework landed (decision 29) | Taproot's identity is a tweak preimage the control block reveals and base consensus authenticates, so the assert reads it at 200 where the derivation assert re-derives it at a point multiplication, the largest single cost in both landed puzzles. Internal key read by self asserts only: decision 26's attacker-satisfiable objection concerns a counterpart's key, not the spending input's own. Ratified 2026-08-22, decision 28. | `validation/self-asserts.json` taptree cases, `conditions/self-asserts.json` and `conditions/costs.json` taptree cases | -| C25 | the annex assert | none: Chia has no annex | ASSERT_MY_ANNEX, a self assert over the BIP341 `sha_annex` digest of the spending input's annex at the generic cost, the annex admitted on a BitLisp spend only under it | Bitcoin's annex is a witness element no operator reads and no BitLisp signature digest commits to, so an ignored annex is third-party malleability on every spend, and a rejected one closes the upgrade path under this leaf version, since a soft fork cannot loosen. Admitting it only under a self assert commits the spender to it, keeps keyless paths safe by default, and leaves the door open. Ratified 2026-09-06, decision 30. | owed to the reference witness layer: `validation/self-asserts.json` and `conditions/self-asserts.json` annex cases | +| C25 | the annex assert | none: Chia has no annex | ASSERT_MY_ANNEX, a self assert over the BIP341 `sha_annex` digest of the spending input's annex at the generic cost, the annex admitted on a BitLisp spend only under it | Bitcoin's annex is a witness element no operator reads and no BitLisp signature digest commits to, so an ignored annex is third-party malleability on every spend, and a rejected one closes the upgrade path under this leaf version, since a soft fork cannot loosen. Admitting it only under a self assert commits the spender to it, keeps keyless paths safe by default, and leaves the door open. Ratified 2026-09-06, decision 30. | landed 2026-09-06 with the reference witness layer: `conditions/self-asserts.json` parses and rejections, `validation/self-asserts.json` both directions, `spend/programs.json` the annex through the witness | ## 2. Reference provenance @@ -1642,8 +1642,10 @@ Section 4 registers the rules that have no external reference at all. the same value. 0x39 follows the taptree assert, 0x34 to 0x37 staying the visible gap. Error `unsatisfied_annex_assert` for the condition and `unasserted_annex` for the witness rule, - each its own vector, both owed to the reference witness layer - with the implementation. + each its own vector, both landed 2026-09-06 with the reference + witness layer: the assert in `conditions/self-asserts.json` and + `validation/self-asserts.json`, the witness rule in + `spend/programs.json` and `spend/witness.json`. ## 4. Novel-layer register diff --git a/docs/glossary.md b/docs/glossary.md index 584d701..2b64064 100644 --- a/docs/glossary.md +++ b/docs/glossary.md @@ -40,6 +40,7 @@ A term enters this table in the same PR that introduces it. | assurer half, requirer half | no direct equivalent | the mode's sender and receiver bit fields | the two commitment values a mode packs, assurer times 32 plus requirer since the execution-identity widening (condition-record decision 26) | | execution identity | tapleaf hash, merkle root, and internal key of the script-path spend | puzzle hash (one field carries both meanings) | the triple validator-filled from the control block: the tapleaf hash and merkle root are specifier fields addressing the executing program and its tree, the internal key is read by self asserts only (condition-record decisions 26 to 28, divergences C23 and C24) | | leaf version | BIP341 term, the control block's first byte with its low bit cleared | none: a coin's puzzle is not versioned | `BITLISP_LEAF_VERSION = 0xd0`, provisional until deployment, the byte that makes a script-path spend a BitLisp spend (spec/SPEC.md section 2.1), glossed 2026-09-06 with the commitment scheme | +| control block | BIP341 term, the last witness element of a script-path spend: leaf version and parity byte, internal key, merkle path | none: a coin spend reveals the puzzle and nothing about a tree | read by the reference for the execution identity and checked against the spent scriptPubKey as base consensus checks it (spec/SPEC.md section 2.3), printed by `bitlisp-commit`, glossed 2026-09-06 | | leaf script | BIP341 term, the script a leaf commits to and a spend reveals | puzzle hash, as the value a coin commits to | the 32-byte tree hash of the committed program, never executed, the program itself a separate witness element the validator checks against it (spec/SPEC.md section 2.2), glossed 2026-09-06 | | per-path leaf | one tapleaf per spending condition, the taproot idiom | none: a puzzle's paths share one puzzle hash | a spend path written as its own curried program in its own leaf, so a spend reveals the executed path and 32 bytes of control block per tree level (spec/SPEC.md section 2.3, commitment-record decisions 7 and 8), glossed 2026-09-06 | | ANNOUNCE, ASSERT_ANNOUNCEMENT | no direct equivalent | the four announcement conditions (coin and puzzle, create and assert) | landed 2026-08-07, the unaddressed pair, namespace first-class, announcer precision chosen by the assert (condition-record decisions 10 and 16) | diff --git a/docs/lang/repl.md b/docs/lang/repl.md index 058257b..faaf886 100644 --- a/docs/lang/repl.md +++ b/docs/lang/repl.md @@ -3,11 +3,12 @@ The interactive front end over the reference VM, the spend runner, the compiler, and the debug machine, all in `python/bitlisp_tools/`. This is tooling, not consensus. The REPL is the `bitlisp` command, -and five one-shot commands ship beside it: `bitlisp-asm` assembles +and six one-shot commands ship beside it: `bitlisp-asm` assembles text to serialized bytecode hex, `bitlisp-disasm` renders hex back as text, `bitlisp-compile` compiles a source program to serialized -bytecode hex, and `bitlisp-curry` and `bitlisp-uncurry` fix values -into a program and split them back out. The text syntax is defined +bytecode hex, `bitlisp-curry` and `bitlisp-uncurry` fix values +into a program and split them back out, and `bitlisp-commit` prints +what an output committing to a program commits to. The text syntax is defined in `syntax.md`, the authoring language in `language.md`, and the currying and tree-hash surfaces in `curry.md`. @@ -198,9 +199,11 @@ bitlisp-compile [--symbols ] [-I ]... [-T] [] bitlisp-curry [-a ]... [-T] [] fix values into a program bitlisp-uncurry [] split a curried program back +bitlisp-commit [--hex] [-k ] [-s ]... [] + leaf, root, control block, scriptPubKey ``` -All five take one argument, a file when one exists at that path +All six take one argument, a file when one exists at that path and the literal otherwise, the `bitlisp-run` convention, or read stdin when the argument is omitted, so they compose in pipelines: @@ -223,6 +226,28 @@ into a hex program, and `bitlisp-uncurry` prints the inner program's hex and then one fixed value per line as text. The curried shape and its contract are defined in `curry.md`. +`bitlisp-commit` takes a program as text, or as serialized hex +under `--hex`, and prints six lines: the leaf script (the program's +tree hash), the tapleaf hash under BitLisp's leaf version, the +merkle root, the internal key, the control block a spend of the +leaf carries, and the taproot scriptPubKey of the output. The leaf +sits alone in its tree unless `-s` names the 32-byte hashes beside +it, leaf upward, and the internal key is the BIP341 +nothing-up-my-sleeve point unless `-k` names one, so the default +output has no key path. It exits 2 when the program does not parse, +a hash or key is not 32 bytes of hex, or the key does not lift to a +curve point. + +``` +$ bitlisp-compile vault.bl | bitlisp-commit --hex +leaf script: ... +tapleaf: ... +merkle root: ... +internal key: 50929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0 +control block: d050929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0 +scriptPubKey: 5120... +``` + `bitlisp-asm`, `bitlisp-disasm`, `bitlisp-compile`, and `bitlisp-curry` take `-T`, printing the program's tree hash instead of their usual output. The digest names the tree, not the diff --git a/docs/vm-record.md b/docs/vm-record.md index 8dd3e2e..4c8af5b 100644 --- a/docs/vm-record.md +++ b/docs/vm-record.md @@ -424,8 +424,9 @@ marked open name the phase that owes the answer. separation. The owed statement is that context argument, written down and pinned. Written down 2026-09-06: `spec/SPEC.md` section 2.4 states the disjointness as a first-byte fact over - every tag in use (commitment-record decision 3), and the vector - lands with the reference witness layer. + every tag in use (commitment-record decision 3), pinned + 2026-09-06 by the test that recomputes the table from the tags + the implementation hashes under. 8. **Peak memory and evaluation order.** OPEN, owed with the Phase 4 budget mapping (recorded 2026-08-16 from the public record in ยง8.5 of the evaluation doc). CLVM costing charges total From 6bcbe76327a04ca05610941254dc03da35bae211 Mon Sep 17 00:00:00 2001 From: Evan Date: Sun, 6 Sep 2026 14:13:31 -0700 Subject: [PATCH 10/17] secp256k1: the x-only tweak helper is dead code taproot_output_key now reads the x coordinate off taproot_output_point, so _apply_tweak had no caller in the consensus path, which the mutation pass showed as a survivor. Removed. Its three boundary tests, the scalar at the group order, the scalar one below it, and the sum at infinity, move onto _tweaked_point and compare points. --- python/bitlisp/secp256k1.py | 8 -------- python/tests/test_taproot.py | 8 ++++---- 2 files changed, 4 insertions(+), 12 deletions(-) diff --git a/python/bitlisp/secp256k1.py b/python/bitlisp/secp256k1.py index 947476e..e33a35e 100644 --- a/python/bitlisp/secp256k1.py +++ b/python/bitlisp/secp256k1.py @@ -55,14 +55,6 @@ def _tweaked_point(point, t): return point_add(point, point_mul(t, G)) -def _apply_tweak(point, t): - """The x-only bytes of point + t*G, or None as _tweaked_point.""" - tweaked = _tweaked_point(point, t) - if tweaked is None: - return None - return tweaked[0].to_bytes(32, "big") - - def taproot_output_point(internal_key, merkle_root): """The taproot output point (x, y), or None. diff --git a/python/tests/test_taproot.py b/python/tests/test_taproot.py index 7c0bf2a..a0c09a9 100644 --- a/python/tests/test_taproot.py +++ b/python/tests/test_taproot.py @@ -26,8 +26,8 @@ from bitlisp.secp256k1 import ( # noqa: E402 G, N, - _apply_tweak, _tap_tweak_scalar, + _tweaked_point, lift_x, point_mul, taproot_output_key, @@ -77,19 +77,19 @@ def test_official_script_pubkey(key, root, tweak, outkey, spk): def test_tweak_scalar_at_group_order_rejected(): - assert _apply_tweak(G, N) is None + assert _tweaked_point(G, N) is None def test_tweak_scalar_below_group_order_accepted(): # 2G + (N - 1)G = (N + 1)G = G, so the boundary scalar just below # the order passes and lands back on the generator. - assert _apply_tweak(point_mul(2, G), N - 1) == G[0].to_bytes(32, "big") + assert _tweaked_point(point_mul(2, G), N - 1) == G def test_tweaked_point_at_infinity_rejected(): # kG + (N - k)G = NG, the point at infinity. k = 5 - assert _apply_tweak(point_mul(k, G), N - k) is None + assert _tweaked_point(point_mul(k, G), N - k) is None # --- value defects and width contracts of the public derivation ------------ From 629b04b9edceb09236abcfd39ec6b9d318101d64 Mon Sep 17 00:00:00 2001 From: Evan Date: Sun, 6 Sep 2026 14:13:31 -0700 Subject: [PATCH 11/17] vectors: the annex digest's compact-size boundary The mutation pass moved the compact-size threshold by one and the corpus did not notice: no annex sat on either side of 253 bytes, where BIP341's sha_annex prefix turns three bytes wide. Two cases in spend/programs.json, an annex of 252 bytes under the one-byte prefix and one of 253 under fd plus two little-endian bytes, each asserted by its program (SPEC.md section 3.4). --- vectors/spend/programs.json | 50 +++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/vectors/spend/programs.json b/vectors/spend/programs.json index e23c2d6..c20f18f 100644 --- a/vectors/spend/programs.json +++ b/vectors/spend/programs.json @@ -240,6 +240,56 @@ "annex_hash": "2847213288f0988543a76512fab09684131809d98baa8b93c2cd8a03a0e31d41" } }, + { + "name": "annex_of_252_bytes", + "script_pubkey": "51205e4427d342e1d7ffc0ab4c437d4bcdffba002001741c6d3ed66a266285fab00e", + "witness": [ + "80", + "ff01ffff39ffa0fee23762af5c5cb22449d9c219589cc3e29cfa2c5f85509a42020105ab51bec78080", + "ed2114a7d9c0bef8d5612883914b794f4ec970fd00021586be2dd7f7301694de", + "d050929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0", + "505a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a" + ], + "max_cost": 10000000, + "expect": { + "conditions": [ + { + "opcode": 57, + "annex_hash": "fee23762af5c5cb22449d9c219589cc3e29cfa2c5f85509a42020105ab51bec7" + } + ], + "tapleaf": "1a4236038d551723615ef45f53e2ce35fb57a385397d682971415be5535de02c", + "merkle_root": "1a4236038d551723615ef45f53e2ce35fb57a385397d682971415be5535de02c", + "internal_key": "50929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0", + "cost": 220, + "annex_hash": "fee23762af5c5cb22449d9c219589cc3e29cfa2c5f85509a42020105ab51bec7" + } + }, + { + "name": "annex_of_253_bytes", + "script_pubkey": "512074f3bf2c0fb433bce1b74469503aec37c4a1443b5c743555d9974a347464414e", + "witness": [ + "80", + "ff01ffff39ffa0c03a438cfc13c574029971d85dc0613e9d69f67d38740230e2523d90cdc51e938080", + "41ed59b405c1564240e7c681b9374595cefd0e32462a66f780e930eab3467eca", + "d050929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0", + "505a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a" + ], + "max_cost": 10000000, + "expect": { + "conditions": [ + { + "opcode": 57, + "annex_hash": "c03a438cfc13c574029971d85dc0613e9d69f67d38740230e2523d90cdc51e93" + } + ], + "tapleaf": "8e6ddf1054e319db81b6c3b0dfa572bc772810f2655e807ec6adfd16ea4b3990", + "merkle_root": "8e6ddf1054e319db81b6c3b0dfa572bc772810f2655e807ec6adfd16ea4b3990", + "internal_key": "50929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0", + "cost": 220, + "annex_hash": "c03a438cfc13c574029971d85dc0613e9d69f67d38740230e2523d90cdc51e93" + } + }, { "name": "spender_supplied_annex_assert", "script_pubkey": "5120864ac98761331f672c01124a5a08e77402420ff7e471bd38cf5ce354a104a194", From 7b118c5238d2eda4a0daae9203a427bf04d9a01b Mon Sep 17 00:00:00 2001 From: Evan Date: Sun, 6 Sep 2026 14:13:31 -0700 Subject: [PATCH 12/17] docs: the mutation pass of 2026-09-06 The seven touched modules, 1,027 mutants. Every survivor in the two new modules falls to the pytest suite. One gap became a vector, one dead function was removed, and one survivor class is new: checks base consensus makes before a spend reaches BitLisp, which the spend suite treats as malformed by design and no vector can kill. --- docs/mutation-triage.md | 55 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/docs/mutation-triage.md b/docs/mutation-triage.md index 03808c7..6ccc505 100644 --- a/docs/mutation-triage.md +++ b/docs/mutation-triage.md @@ -182,6 +182,61 @@ no signer reaches without about 2^128 work, `r` at or above `P` likewise, and a tweak scalar of exactly `N` is a hash preimage. The group order itself moved by one changes only those checks. +## Pass of 2026-09-06 + +Run on the witness-layer branch over the seven modules it touched +(`commitment` and `spend` new, `conditions`, `validation`, `tx`, +`errors`, and `secp256k1` changed), the corpus at 1,199 cases before +this pass's additions, with `--tests`. + +| module | mutants | killed | crashed | survived | timeout | +| --- | --- | --- | --- | --- | --- | +| commitment | 100 | 48 | 24 | 28 | 0 | +| conditions | 397 | 315 | 41 | 41 | 0 | +| errors | 2 | 0 | 1 | 1 | 0 | +| secp256k1 | 153 | 105 | 26 | 20 | 2 | +| spend | 45 | 36 | 2 | 7 | 0 | +| tx | 178 | 100 | 14 | 64 | 0 | +| validation | 152 | 128 | 17 | 7 | 0 | +| total | 1,027 | 732 | 125 | 168 | 2 | + +Every survivor in the two new modules is killed by the pytest +suite, 35 of 35. Three things came out of reading them. + +One gap, one vector: the compact-size prefix of the annex digest +turns three bytes wide at 253, and no annex case sat on either side +of the boundary, so `n < 0xFD` moved by one survived the corpus. +`spend/programs.json` gains `annex_of_252_bytes` and +`annex_of_253_bytes` (SPEC.md section 3.4). The wider forms at +65,536 and 2^32 bytes lie above `MAX_WITNESS_ELEMENT_SIZE` and no +element reaches them: beyond reach. + +One dead function: `_apply_tweak` in `secp256k1.py` survived under +the corpus because nothing in the consensus path called it once +`taproot_output_point` landed. Removed, its tests moved onto +`_tweaked_point`. + +One new survivor class, **outside BitLisp by design**: the control +block length bound, the leaf version check, the key lift, the tweak +check, and the parity check in `commitment.py` and `spend.py`, and +the two-element threshold of the annex split. A witness that fails +them is refused by base consensus or is not a BitLisp spend, SPEC.md +assigns it no outcome, and the spend suite treats such a case as +malformed rather than pinning it, so no vector can kill these +mutants. The pytest suite kills every one (the BIP341 differential +and the base-consensus tests in `test_spend.py`). In the same file, +the sibling sort's `<` to `<=` is equivalent: two equal hashes +concatenate to the same bytes in either order. + +The other modules' survivors are the accepted classes above. The +one new survivor in `conditions.py` is the frozen flag of +`AssertMyAnnex` (equivalent), the three new in `tx.py` are the +`annex_hash` width check (model precondition), and the five new in +`secp256k1.py` are the width guard and value defects of +`taproot_output_point` (unreachable guard, beyond reach), the same +sites `taproot_output_key` carried before it. `validation.py` stays +at seven. + ## Re-running A pass belongs with any change to `python/bitlisp/` that adds a From d907f8ca4cd09467bcb8a69fe78f62548eb32660 Mon Sep 17 00:00:00 2001 From: Evan Date: Sun, 6 Sep 2026 14:41:24 -0700 Subject: [PATCH 13/17] spec: review fold-ins, the family of six and the view's annex hash CONDITIONS.md's self assert heading and count still read five conditions at 0x30 to 0x33 and 0x38 while the entry for 0x39, the cost table's "each self assert" row, and the implementation all file ASSERT_MY_ANNEX under the family. Six, with the annex hash named among the facts the family reads. VALIDATION.md's transaction view said an input without a condition list may carry the triple or not. It may carry annexHash or not on the same terms, and no rule reads either: the sentence now says so, the vector annex_on_plain_input_unread having pinned a shape the spec did not name. --- spec/CONDITIONS.md | 11 ++++++----- spec/VALIDATION.md | 3 ++- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/spec/CONDITIONS.md b/spec/CONDITIONS.md index 198a3ff..702ed72 100644 --- a/spec/CONDITIONS.md +++ b/spec/CONDITIONS.md @@ -458,12 +458,13 @@ charged after every argument check. **Validation rule.** The assert clause of VALIDATION.md (claims and asserts, rule 2). Stage 4. -### Self asserts (`0x30` to `0x33`, `0x38`) +### Self asserts (`0x30` to `0x33`, `0x38`, `0x39`) -The five conditions of this family assert facts of the spending -input's own prevout data and execution identity: the outpoint it -consumes, the creating txid, the spent scriptPubKey, the amount, -and the internal key and merkle root its control block carries. +The six conditions of this family assert facts of the spending +input's own prevout data, execution identity, and witness: the +outpoint it consumes, the creating txid, the spent scriptPubKey, +the amount, the internal key and merkle root its control block +carries, and the hash of the annex its witness carries. Every assert is an equality against that input's own data in the transaction view. Nothing in this family reads another input, an output slot, or a transaction-level field. diff --git a/spec/VALIDATION.md b/spec/VALIDATION.md index 2152342..6c0ace6 100644 --- a/spec/VALIDATION.md +++ b/spec/VALIDATION.md @@ -62,7 +62,8 @@ A transaction is: reads `internalKey` or `annexHash`. Only conditions reach these fields: an input without a condition list, whether a non-BitLisp input or a BitLisp spend whose evaluation has not yet produced one, may - carry the triple or not, and no rule reads it from either. + carry the triple and `annexHash` or not, and no rule reads them + from either. - `outputs`, an ordered list of slots. Each slot's content is the pair (`scriptPubKey`, `amount`). Slots are addressed by index. From bd8925508323bc52f46c747d00bd8a440f645e2f Mon Sep 17 00:00:00 2001 From: Evan Date: Sun, 6 Sep 2026 14:41:24 -0700 Subject: [PATCH 14/17] spend: review fold-ins, one tagged hash and one compact size Four spellings of BIP340's tagged hash became one, secp256k1's tagged_hash, which the challenge digest, the tweak scalar, the leaf and branch hashes, and the signature-assert digests all call. The digest-domain test now scans that one function's call sites, so a new tag cannot enter the package unseen. tx.py's compact-size prefix was a copy of commitment.py's and imports it instead. The tree hash is the sha256tree operator run with its charges discarded, not a second copy of its walk. conditions.py derives a taproot scriptPubKey through commitment.taproot_script_pubkey, which gives that function its consensus caller. The annex admission rule moves to spend.py, the per-input stage it belongs to, and validate_transaction imports it, so the dependency runs from the later stage to the earlier one. ControlBlock gains build, which derives the parity bit from the output key, and serialize, the inverse of parse, so the forward construction exists in the library once. The tree hash on the leaf_mismatch path is computed once, and TxInput's four optional 32-byte fields share one width check. --- python/bitlisp/commitment.py | 64 +++++++++++++++++++----------------- python/bitlisp/conditions.py | 8 ++--- python/bitlisp/secp256k1.py | 16 +++++---- python/bitlisp/spend.py | 28 +++++++++++++--- python/bitlisp/tx.py | 41 +++++------------------ python/bitlisp/validation.py | 41 +++++------------------ 6 files changed, 89 insertions(+), 109 deletions(-) diff --git a/python/bitlisp/commitment.py b/python/bitlisp/commitment.py index 8d92feb..f594ed9 100644 --- a/python/bitlisp/commitment.py +++ b/python/bitlisp/commitment.py @@ -6,7 +6,8 @@ hash, never executed, and the program itself travels in the witness to be checked against it. Everything here is hashing: the tree hash over a node, BIP341's tagged hashes over the leaf, the branch fold, -and the annex digest. Point arithmetic stays in secp256k1. +and the annex digest. Point arithmetic and the tagged hash itself +stay in secp256k1. """ import hashlib @@ -14,7 +15,8 @@ from . import secp256k1 from .errors import BaseConsensusError -from .sexp import is_pair +from .operators import op_sha256tree +from .secp256k1 import tagged_hash # PROVISIONAL: fixed at deployment. Any compliant byte works, the low # bit clear, and nothing else in the scheme depends on which one. @@ -31,35 +33,16 @@ ANNEX_TAG = 0x50 +def _uncharged(amount): + """The charge callback of an operator run outside a budget.""" + + def tree_hash(node): - """The tree hash of a node, the value sha256tree computes: an atom - hashes as SHA-256 of 0x01 then its bytes, a pair as SHA-256 of - 0x02 then the first child's hash then the rest child's hash. An - explicit stack, so a deep program never meets the recursion - limit. Uncharged: the caller prices the bytes that carried the - node, not the hashing.""" - hashes = [] - stack = [(False, node)] - while stack: - combine, current = stack.pop() - if combine: - first = hashes.pop() - rest = hashes.pop() - hashes.append(hashlib.sha256(b"\x02" + first + rest).digest()) - elif is_pair(current): - stack.append((True, None)) - stack.append((False, current[0])) - stack.append((False, current[1])) - else: - hashes.append(hashlib.sha256(b"\x01" + current).digest()) - return hashes[0] - - -def tagged_hash(tag, data): - """BIP340's tagged hash: SHA-256 of the tag's digest twice, then - the data. tag is the ASCII tag name.""" - tag_hash = hashlib.sha256(tag.encode("ascii")).digest() - return hashlib.sha256(tag_hash + tag_hash + data).digest() + """The tree hash of a node, the value the sha256tree operator + computes, computed by that operator with its charges discarded: + the caller prices the bytes that carried the node, not the + hashing.""" + return op_sha256tree([node], _uncharged) def compact_size(n): @@ -123,6 +106,27 @@ class ControlBlock: internal_key: bytes path: bytes + @classmethod + def build( + cls, internal_key, leaf_script, path=b"", leaf_version=BITLISP_LEAF_VERSION + ): + """The control block a spend of leaf_script carries under + internal_key with this merkle path: the parity bit is the + output key's, derived here. None when the key does not lift + or the tweak fails, the same value defects taproot_output_point + reports.""" + tapleaf = tapleaf_hash(leaf_version, leaf_script) + output = secp256k1.taproot_output_point( + internal_key, merkle_root(tapleaf, path) + ) + if output is None: + return None + return cls(leaf_version, output[1] & 1, internal_key, path) + + def serialize(self): + """The control block's bytes, the inverse of parse.""" + return bytes([self.leaf_version | self.parity]) + self.internal_key + self.path + @classmethod def parse(cls, data): """Splits a control block, else BaseConsensusError: its length diff --git a/python/bitlisp/conditions.py b/python/bitlisp/conditions.py index 7e2ce16..b0b9611 100644 --- a/python/bitlisp/conditions.py +++ b/python/bitlisp/conditions.py @@ -19,7 +19,7 @@ from dataclasses import dataclass -from . import secp256k1 +from .commitment import taproot_script_pubkey from .costs import ( CONDITION_GENERIC_COST, CONDITION_MESSAGE_COST, @@ -557,12 +557,12 @@ def _derive_taproot_spk(internal_key, merkle_root): condition's cost, so a budget too small for the charge never reaches this derivation and a derivation defect is reported only when the charge is covered.""" - output_key = secp256k1.taproot_output_key(internal_key, merkle_root) - if output_key is None: + script_pubkey = taproot_script_pubkey(internal_key, merkle_root) + if script_pubkey is None: raise BitLispError( "bad_condition_arg", "internal key and merkle root derive no output key" ) - return b"\x51\x20" + output_key + return script_pubkey def _parse_create_output_taproot(args, meter): diff --git a/python/bitlisp/secp256k1.py b/python/bitlisp/secp256k1.py index e33a35e..8025d63 100644 --- a/python/bitlisp/secp256k1.py +++ b/python/bitlisp/secp256k1.py @@ -23,13 +23,18 @@ 0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8, ) -_CHALLENGE_TAG_HASH = hashlib.sha256(b"BIP0340/challenge").digest() -_TWEAK_TAG_HASH = hashlib.sha256(b"TapTweak").digest() + +def tagged_hash(tag, data): + """BIP340's tagged hash: SHA-256 of the tag's digest twice, then + the data. tag is the ASCII tag name. Every tagged digest the + package computes comes through here, so the tags in use are the + strings this function is called with.""" + tag_hash = hashlib.sha256(tag.encode("ascii")).digest() + return hashlib.sha256(tag_hash + tag_hash + data).digest() def _challenge_hash(data): - # The BIP 340 tagged hash: the tag's digest twice, then the data. - return hashlib.sha256(_CHALLENGE_TAG_HASH + _CHALLENGE_TAG_HASH + data).digest() + return tagged_hash("BIP0340/challenge", data) def _tap_tweak_scalar(internal_key, merkle_root): @@ -39,8 +44,7 @@ def _tap_tweak_scalar(internal_key, merkle_root): An empty merkle_root leaves the internal key alone, which is the key-only tweak of an output committing to no script tree. """ - data = _TWEAK_TAG_HASH + _TWEAK_TAG_HASH + internal_key + merkle_root - return int.from_bytes(hashlib.sha256(data).digest(), "big") + return int.from_bytes(tagged_hash("TapTweak", internal_key + merkle_root), "big") def _tweaked_point(point, t): diff --git a/python/bitlisp/spend.py b/python/bitlisp/spend.py index 848b64f..9221420 100644 --- a/python/bitlisp/spend.py +++ b/python/bitlisp/spend.py @@ -22,11 +22,10 @@ sha_annex, tree_hash, ) -from .conditions import parse_conditions +from .conditions import AssertMyAnnex, parse_conditions from .errors import BaseConsensusError, BitLispError from .machine import run from .serialize import deserialize -from .validation import check_annex_admission # The solution, the program, the leaf script, and the control block. WITNESS_ELEMENT_COUNT = 4 @@ -70,6 +69,26 @@ def read_identity(elements, script_pubkey): return tapleaf, root, control_block.internal_key +def check_annex_admission(tx_input): + """The annex rule: an input whose witness carries an annex is + valid only when its condition list holds an ASSERT_MY_ANNEX, so + the annex is data the spender committed to and no third party + can attach one. The rule reads the input alone, so it runs here + right after the input's conditions parse, and validate_transaction + runs it again over every assembled input, because a transaction + view built without evaluate_spend must satisfy the same invariant. + An input without a condition list is not a BitLisp input and + carries no annex the rule reads.""" + if tx_input.annex_hash is None or tx_input.conditions is None: + return + if not any(isinstance(cond, AssertMyAnnex) for cond in tx_input.conditions): + raise BitLispError( + "unasserted_annex", + f"the witness carries an annex hashing to {tx_input.annex_hash.hex()} " + "and the condition list holds no ASSERT_MY_ANNEX", + ) + + def evaluate_spend(tx_input, witness, max_cost): """Runs one input's spend through every per-input stage. @@ -119,10 +138,11 @@ def evaluate_spend(tx_input, witness, max_cost): # Stage 2: the program decodes and is the one the leaf commits to. program = deserialize(program_bytes) - if tree_hash(program) != leaf_script: + program_hash = tree_hash(program) + if program_hash != leaf_script: raise BitLispError( "leaf_mismatch", - f"the program's tree hash {tree_hash(program).hex()} is not the leaf " + f"the program's tree hash {program_hash.hex()} is not the leaf " f"script {leaf_script.hex()}", ) diff --git a/python/bitlisp/tx.py b/python/bitlisp/tx.py index 3f90503..0f77e81 100644 --- a/python/bitlisp/tx.py +++ b/python/bitlisp/tx.py @@ -11,23 +11,12 @@ import hashlib from dataclasses import dataclass +from .commitment import compact_size from .conditions import MAX_MONEY _UINT32_MAX = 0xFFFFFFFF -def _compact_size(n): - """Bitcoin's variable-length count prefix, the wire encoding of - list lengths and byte-string lengths.""" - if n < 0xFD: - return n.to_bytes(1, "little") - if n <= 0xFFFF: - return b"\xfd" + n.to_bytes(2, "little") - if n <= 0xFFFFFFFF: - return b"\xfe" + n.to_bytes(4, "little") - return b"\xff" + n.to_bytes(8, "little") - - def _check_amount(amount, what): if not isinstance(amount, int) or not 0 <= amount <= MAX_MONEY: raise ValueError(f"{what} amount out of range: {amount!r}") @@ -84,22 +73,10 @@ def __post_init__(self): raise ValueError("conditions must be a tuple or None") if not isinstance(self.script_sig, bytes): raise ValueError("scriptSig must be bytes") - if self.tapleaf is not None and ( - not isinstance(self.tapleaf, bytes) or len(self.tapleaf) != 32 - ): - raise ValueError("tapleaf must be 32 bytes") - if self.merkle_root is not None and ( - not isinstance(self.merkle_root, bytes) or len(self.merkle_root) != 32 - ): - raise ValueError("merkle_root must be 32 bytes") - if self.internal_key is not None and ( - not isinstance(self.internal_key, bytes) or len(self.internal_key) != 32 - ): - raise ValueError("internal_key must be 32 bytes") - if self.annex_hash is not None and ( - not isinstance(self.annex_hash, bytes) or len(self.annex_hash) != 32 - ): - raise ValueError("annex_hash must be 32 bytes") + for name in ("tapleaf", "merkle_root", "internal_key", "annex_hash"): + value = getattr(self, name) + if value is not None and (not isinstance(value, bytes) or len(value) != 32): + raise ValueError(f"{name} must be 32 bytes") if self.conditions is not None and ( self.tapleaf is None or self.merkle_root is None @@ -136,7 +113,7 @@ def wire(self): amount, then the length-prefixed scriptPubKey.""" return ( self.amount.to_bytes(8, "little") - + _compact_size(len(self.script_pubkey)) + + compact_size(len(self.script_pubkey)) + self.script_pubkey ) @@ -185,13 +162,13 @@ def txid(self): carries changes this value. Distinct from an input's txid, which names the past transaction that created its prevout.""" data = bytearray(self.version.to_bytes(4, "little")) - data += _compact_size(len(self.inputs)) + data += compact_size(len(self.inputs)) for tx_input in self.inputs: data += tx_input.txid data += tx_input.index.to_bytes(4, "little") - data += _compact_size(len(tx_input.script_sig)) + tx_input.script_sig + data += compact_size(len(tx_input.script_sig)) + tx_input.script_sig data += tx_input.sequence.to_bytes(4, "little") - data += _compact_size(len(self.outputs)) + data += compact_size(len(self.outputs)) for output in self.outputs: data += output.wire data += self.locktime.to_bytes(4, "little") diff --git a/python/bitlisp/validation.py b/python/bitlisp/validation.py index 83784a7..5baf00e 100644 --- a/python/bitlisp/validation.py +++ b/python/bitlisp/validation.py @@ -82,6 +82,7 @@ Specifier, ) from .errors import BitLispError +from .spend import check_annex_admission _SEQUENCE_FINAL = 0xFFFFFFFF _SEQUENCE_DISABLE_FLAG = 1 << 31 @@ -253,26 +254,6 @@ def check_self_asserts(tx): ) -def check_annex_admission(tx_input): - """The annex rule: an input whose witness carries an annex is - valid only when its condition list holds an ASSERT_MY_ANNEX, so - the annex is data the spender committed to and no third party - can attach one. The rule reads the input alone, so the spend - pipeline runs it right after the input's conditions parse, and - validate_transaction runs it again over every assembled input, - because a transaction view built without the pipeline must - satisfy the same invariant. An input without a condition list - is not a BitLisp input and carries no annex the rule reads.""" - if tx_input.annex_hash is None or tx_input.conditions is None: - return - if not any(isinstance(cond, AssertMyAnnex) for cond in tx_input.conditions): - raise BitLispError( - "unasserted_annex", - f"the witness carries an annex hashing to {tx_input.annex_hash.hex()} " - "and the condition list holds no ASSERT_MY_ANNEX", - ) - - def self_specifier(tx_input, commitment): """The input's own prevout data and execution identity at a commitment value: what an ASSURE or REQUIRE says about its @@ -363,19 +344,13 @@ def check_announcements(tx): ) -_SIG_TAG_HASHES = { - opcode: hashlib.sha256(tag.encode("ascii")).digest() - for opcode, (_, tag, _) in SIG_BINDINGS.items() -} - - def _sig_digest(cond, tx_input): - """The tagged-hash digest a signature assert verifies against: - sha256(sha256(tag) || sha256(tag) || binding fields || message), - the fields fixed-length ahead of the variable-length message.""" - tag_hash = _SIG_TAG_HASHES[cond.opcode] - data = bytearray(tag_hash + tag_hash) - for kind in SIG_BINDINGS[cond.opcode][2]: + """The tagged-hash digest a signature assert verifies against: the + binding's tag over the binding fields then the message, the + fields fixed-length ahead of the variable-length message.""" + _, tag, kinds = SIG_BINDINGS[cond.opcode] + data = bytearray() + for kind in kinds: if kind == "txid": data += tx_input.txid elif kind == "spk_hash": @@ -387,7 +362,7 @@ def _sig_digest(cond, tx_input): else: raise AssertionError(f"unknown binding field {kind!r}") data += cond.message - return hashlib.sha256(data).digest() + return secp256k1.tagged_hash(tag, bytes(data)) def check_signature_asserts(tx): From 586fdcc7593658c9e768352eaf2ee7290cda9a64 Mon Sep 17 00:00:00 2001 From: Evan Date: Sun, 6 Sep 2026 14:41:24 -0700 Subject: [PATCH 15/17] tools: review fold-ins for bitlisp-commit The command refused nothing above 128 siblings and printed a control block and scriptPubKey for a leaf base consensus can never spend. It now exits 2 past MERKLE_PATH_MAX_DEPTH. The control block comes from ControlBlock.build and the scriptPubKey from taproot_script_pubkey rather than hand assembly, and the doc says the first byte's low bit is the output key's parity, so d0 and d1 are both expected. The tools package imports the tree hash from the consensus module directly. --- python/bitlisp_tools/__init__.py | 3 ++- python/bitlisp_tools/cli.py | 35 ++++++++++++++++++++------------ 2 files changed, 24 insertions(+), 14 deletions(-) diff --git a/python/bitlisp_tools/__init__.py b/python/bitlisp_tools/__init__.py index 3fa7549..2c8c632 100644 --- a/python/bitlisp_tools/__init__.py +++ b/python/bitlisp_tools/__init__.py @@ -6,6 +6,8 @@ code, and nothing in the consensus package depends on it. """ +from bitlisp.commitment import tree_hash + from .compiler import ( CONDITION_CONSTANTS, RESERVED_WORDS, @@ -17,7 +19,6 @@ parse_source, parse_source_many, symbols_to_json, - tree_hash, ) from .curry import curry, uncurry from .keywords import ATOM_TO_NAME, NAME_TO_ATOM diff --git a/python/bitlisp_tools/cli.py b/python/bitlisp_tools/cli.py index 8ae2470..f400c89 100644 --- a/python/bitlisp_tools/cli.py +++ b/python/bitlisp_tools/cli.py @@ -23,11 +23,13 @@ from bitlisp import BitLispError, deserialize, serialize from bitlisp.commitment import ( BITLISP_LEAF_VERSION, + MERKLE_PATH_MAX_DEPTH, + ControlBlock, merkle_root, tapleaf_hash, + taproot_script_pubkey, tree_hash, ) -from bitlisp.secp256k1 import taproot_output_point from .compiler import CompileError, compile_program, symbols_to_json from .curry import curry, uncurry @@ -224,17 +226,21 @@ the leaf's position in its tree, the internal key, the control block a spend of the leaf carries, and the taproot scriptPubKey of the output. The leaf sits alone in its tree unless --sibling names -the 32-byte hashes beside it, leaf upward, in which case the merkle -root and the control block carry that path. The internal key is the -BIP341 nothing-up-my-sleeve point unless --internal-key names one, -so the default output has no key path. +the 32-byte hashes beside it, leaf upward, at most 128 of them, in +which case the merkle root and the control block carry that path. +The internal key is the BIP341 nothing-up-my-sleeve point unless +--internal-key names one, so the default output has no key path. +The control block's first byte is the leaf version with the output +key's parity in its low bit, so it reads d0 or d1 depending on the +key and the tree. The program argument names a file when one exists at that path and reads as the literal otherwise, or comes from stdin when omitted. Exit status 0 on success, 2 when the program does not parse, a hash -or key is not 32 bytes of hex, the internal key does not lift to a -curve point, or the file does not open. +or key is not 32 bytes of hex, there are more than 128 siblings, +the internal key does not lift to a curve point, or the file does +not open. Usage: bitlisp-compile vault.bl | bitlisp-commit --hex @@ -289,12 +295,17 @@ def commit_main(argv=None): try: program = _node(_input_text(args.program), args.hex) internal_key = _hex32(args.internal_key, "internal key") + if len(args.sibling) > MERKLE_PATH_MAX_DEPTH: + raise ValueError( + f"a merkle path holds at most {MERKLE_PATH_MAX_DEPTH} siblings, " + f"got {len(args.sibling)}" + ) path = b"".join(_hex32(sibling, "sibling") for sibling in args.sibling) leaf_script = tree_hash(program) tapleaf = tapleaf_hash(BITLISP_LEAF_VERSION, leaf_script) root = merkle_root(tapleaf, path) - output = taproot_output_point(internal_key, root) - if output is None: + control_block = ControlBlock.build(internal_key, leaf_script, path) + if control_block is None: raise ValueError("the internal key does not lift to a curve point") except BitLispError as exc: print(f"error: {exc.code}: {exc}", file=sys.stderr) @@ -302,15 +313,13 @@ def commit_main(argv=None): except (ParseError, OSError, ValueError) as exc: print(f"error: {exc}", file=sys.stderr) return 2 - x, y = output - control_block = bytes([BITLISP_LEAF_VERSION | (y & 1)]) + internal_key + path lines = ( ("leaf script", leaf_script), ("tapleaf", tapleaf), ("merkle root", root), ("internal key", internal_key), - ("control block", control_block), - ("scriptPubKey", b"\x51\x20" + x.to_bytes(32, "big")), + ("control block", control_block.serialize()), + ("scriptPubKey", taproot_script_pubkey(internal_key, root)), ) with _pipe_shield(): for label, value in lines: From ff05ed26a8adab6c46912d7285016bb7f121e631 Mon Sep 17 00:00:00 2001 From: Evan Date: Sun, 6 Sep 2026 14:41:24 -0700 Subject: [PATCH 16/17] tests: review fold-ins for the witness layer The digest-domain completeness test scanned a fixed tuple of four tags, so a new tagged_hash call would have passed it. It now collects every literal tag at a tagged_hash call site plus the signature bindings' tags, and checks the function is defined once. A round-trip property covers ControlBlock.build, serialize, parse, and check together. The lone self assert equality property draws an annex only under an annex assert again, so the five older families reach the equality check on every example rather than a third of them, the admission rule having its own property. --- python/tests/test_self_assert_invariants.py | 13 ++-- python/tests/test_spend.py | 84 +++++++++++++-------- 2 files changed, 59 insertions(+), 38 deletions(-) diff --git a/python/tests/test_self_assert_invariants.py b/python/tests/test_self_assert_invariants.py index b93d288..a3ca7b4 100644 --- a/python/tests/test_self_assert_invariants.py +++ b/python/tests/test_self_assert_invariants.py @@ -195,9 +195,11 @@ def test_single_assert_outcome_matches_field_equality( ): """A lone self assert is satisfied exactly when each operand equals the field it reads, and fails with its field's error - otherwise. An input carrying an annex under any other lone - assert fails the admission rule instead, whatever that assert - would have said.""" + otherwise. The input carries an annex only under an annex + assert: under any other lone assert an annex fails the admission + rule first, the property the admission test pins.""" + if not isinstance(cond, AssertMyAnnex): + annex = None if isinstance(cond, AssertMyOutpoint): satisfied = cond.outpoint == _outpoint(txid, index) error = "unsatisfied_outpoint_assert" @@ -217,10 +219,7 @@ def test_single_assert_outcome_matches_field_equality( satisfied = cond.amount == amount error = "unsatisfied_amount_assert" got = outcome(build_tx(txid, index, script, amount, [cond], env, identity, annex)) - if annex is not None and not isinstance(cond, AssertMyAnnex): - assert got == "unasserted_annex" - else: - assert got == (None if satisfied else error) + assert got == (None if satisfied else error) @given( diff --git a/python/tests/test_spend.py b/python/tests/test_spend.py index dcd4141..cbe66dc 100644 --- a/python/tests/test_spend.py +++ b/python/tests/test_spend.py @@ -15,6 +15,7 @@ import hashlib import json +import re import sys from pathlib import Path @@ -45,7 +46,6 @@ tree_hash, ) from bitlisp.operators import op_sha256tree # noqa: E402 -from bitlisp.secp256k1 import taproot_output_point # noqa: E402 from bitlisp.spend import MAX_WITNESS_ELEMENT_SIZE, split_annex # noqa: E402 from support import NUMS # noqa: E402 from test_framework.key import TaggedHash # noqa: E402 @@ -237,17 +237,24 @@ def test_digest_domain_table_first_bytes(): def test_digest_domain_table_is_every_tag_the_package_hashes_under(): + """Every tagged digest goes through secp256k1.tagged_hash, so the + tags in use are its literal arguments plus the signature bindings' + tags, and the table must be exactly that set.""" from bitlisp.conditions import SIG_BINDINGS package = REPO_ROOT / "python" / "bitlisp" - sig_tags = {binding[1] for binding in SIG_BINDINGS.values()} - literal_tags = set() + literal = re.compile(r'tagged_hash\(\s*"([^"]+)"') + tags = {binding[1] for binding in SIG_BINDINGS.values()} for path in package.glob("*.py"): - text = path.read_text() - for tag in ("TapLeaf", "TapBranch", "TapTweak", "BIP0340/challenge"): - if f'"{tag}"' in text or f'b"{tag}"' in text: - literal_tags.add(tag) - assert sig_tags | literal_tags == set(DIGEST_DOMAIN_TABLE) + tags.update(literal.findall(path.read_text())) + assert tags == set(DIGEST_DOMAIN_TABLE) + # One tagged hash, in one place, so the scan above sees every tag. + definitions = [ + path.name + for path in package.glob("*.py") + if "def tagged_hash(" in path.read_text() + ] + assert definitions == ["secp256k1.py"] # --- the spend entry's invariants ------------------------------------------ @@ -261,15 +268,15 @@ def _clist(*items): def _spend(program, solution, annex=None, path=b"", max_cost=10_000_000): - """Evaluates a program over a solution as a single-leaf spend under - NUMS, returning (cost, input) or the error code.""" + """Evaluates a program over a solution as a spend of a leaf under + NUMS with the given path, returning (cost, input) or the error + code.""" leaf = tree_hash(program) - root = merkle_root(tapleaf_hash(BITLISP_LEAF_VERSION, leaf), path) - x, y = taproot_output_point(NUMS, root) - block = bytes([BITLISP_LEAF_VERSION | (y & 1)]) + NUMS + path - witness = [serialize(solution), serialize(program), leaf, block] + block = ControlBlock.build(NUMS, leaf, path) + witness = [serialize(solution), serialize(program), leaf, block.serialize()] if annex is not None: witness.append(annex) + root = merkle_root(tapleaf_hash(BITLISP_LEAF_VERSION, leaf), path) tx_input = TxInput(b"\x00" * 32, 0, taproot_script_pubkey(NUMS, root), 1, 0) try: return evaluate_spend(tx_input, witness, max_cost) @@ -349,27 +356,42 @@ def test_split_annex_follows_bip341(): def test_key_path_and_foreign_leaf_versions_are_outside_bitlisp(): leaf = tree_hash(b"\x01") + block = ControlBlock.build(NUMS, leaf, leaf_version=0xC0).serialize() root = merkle_root(tapleaf_hash(0xC0, leaf), b"") - x, y = taproot_output_point(NUMS, root) - block = bytes([0xC0 | (y & 1)]) + NUMS tx_input = TxInput(b"\x00" * 32, 0, taproot_script_pubkey(NUMS, root), 1, 0) with pytest.raises(BaseConsensusError, match="leaf version"): evaluate_spend(tx_input, [b"\x80", b"\x01", leaf, block], 1000) with pytest.raises(BaseConsensusError, match="not a script-path spend"): evaluate_spend(tx_input, [b"\x00" * 64], 1000) + carrying = TxInput( + b"\x00" * 32, + 0, + b"\x51", + 1, + 0, + conditions=(), + tapleaf=leaf, + merkle_root=leaf, + internal_key=NUMS, + ) with pytest.raises(ValueError, match="already carries"): - evaluate_spend( - TxInput( - b"\x00" * 32, - 0, - b"\x51", - 1, - 0, - conditions=(), - tapleaf=leaf, - merkle_root=leaf, - internal_key=NUMS, - ), - [b"\x80", b"\x01", leaf, block], - 1000, - ) + evaluate_spend(carrying, [b"\x80", b"\x01", leaf, block], 1000) + + +@EXAMPLES +@given( + st.integers(0, 127).map(lambda v: v * 2), + st.lists(st.binary(min_size=32, max_size=32), max_size=5), + st.binary(max_size=40), +) +def test_control_block_round_trips(leaf_version, siblings, leaf_script): + """build then serialize then parse gives the block back, its + parity the output key's, and build reports None exactly when the + key does not lift.""" + path = b"".join(siblings) + block = ControlBlock.build(NUMS, leaf_script, path, leaf_version) + assert ControlBlock.parse(block.serialize()) == block + assert block.check( + leaf_script, taproot_script_pubkey(NUMS, block.identity(leaf_script)[1]) + ) + assert ControlBlock.build(b"\xff" * 32, leaf_script, path, leaf_version) is None From 2507c52344998a4afcf93fa52ce0e2ab7a065976 Mon Sep 17 00:00:00 2001 From: Evan Date: Sun, 6 Sep 2026 14:41:24 -0700 Subject: [PATCH 17/17] docs: review fold-ins for the witness layer The REPL doc's bitlisp-commit example showed a control block whose first byte the reader would take as constant. It now shows the real output for the atom 1 and says the low bit is the output key's parity. The commitment record states why the digest-domain table is pinned by a test rather than the vector decision 3 first promised, and where the annex rule lives. --- docs/commitment-record.md | 15 ++++++++++----- docs/lang/repl.md | 19 +++++++++++-------- 2 files changed, 21 insertions(+), 13 deletions(-) diff --git a/docs/commitment-record.md b/docs/commitment-record.md index 9d1709b..484155b 100644 --- a/docs/commitment-record.md +++ b/docs/commitment-record.md @@ -129,10 +129,13 @@ the trigger. one, the check that keeps the argument true. TapSighash is base consensus's key-path digest, computed by no BitLisp rule, and its first byte is `0xf4` regardless. The table is pinned by a - test that recomputes every row from the tag strings the - implementation hashes under and checks the set of rows is exactly - the set of tags in use (landed 2026-09-06 with the reference - witness layer). Writing that test found the challenge row wrong: + test rather than the vector this entry first promised (decision + by Evan, 2026-09-06, steelmanned both ways): the table fits no + suite's case shape, and a test can state the argument as well as + the values, recomputing every row from the tag strings and + checking that the rows are exactly the tags in use, every tagged + digest passing through one function. Writing that test found the + challenge row wrong: the table had named the tag `BIP340/challenge` with first byte `0x07`, and BIP340 spells it `BIP0340/challenge`, first byte `0x7b`. Corrected the same day, the argument unchanged. @@ -339,7 +342,9 @@ Three choices made there, none a change to the scheme: reference path, at stage 5 by the spend entry and first in transaction validation, because the validation vectors and the runner assemble transaction views without the spend entry and - the view's invariant must hold for them too. + the view's invariant must hold for them too. It lives with the + per-input stages, and transaction validation imports it, so the + dependency runs from the later stage to the earlier one. - The witness form of `bitlisp-run` and the REPL is deferred to unit 9's first PR, where the vault is the first consumer. diff --git a/docs/lang/repl.md b/docs/lang/repl.md index faaf886..a88a96a 100644 --- a/docs/lang/repl.md +++ b/docs/lang/repl.md @@ -234,18 +234,21 @@ leaf carries, and the taproot scriptPubKey of the output. The leaf sits alone in its tree unless `-s` names the 32-byte hashes beside it, leaf upward, and the internal key is the BIP341 nothing-up-my-sleeve point unless `-k` names one, so the default -output has no key path. It exits 2 when the program does not parse, -a hash or key is not 32 bytes of hex, or the key does not lift to a -curve point. +output has no key path. The control block's first byte is the leaf +version `0xd0` with the output key's parity in its low bit, so it +reads `d0` or `d1` depending on the key and the tree. It exits 2 +when the program does not parse, a hash or key is not 32 bytes of +hex, there are more than 128 siblings, or the key does not lift to +a curve point. ``` -$ bitlisp-compile vault.bl | bitlisp-commit --hex -leaf script: ... -tapleaf: ... -merkle root: ... +$ bitlisp-commit "1" +leaf script: 9dcf97a184f32623d11a73124ceb99a5709b083721e878a16d78f596718ba7b2 +tapleaf: dde54461ef9453a9d235b60142c77f6680d0243ec4a02d206750059e8ea08b95 +merkle root: dde54461ef9453a9d235b60142c77f6680d0243ec4a02d206750059e8ea08b95 internal key: 50929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0 control block: d050929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0 -scriptPubKey: 5120... +scriptPubKey: 5120864ac98761331f672c01124a5a08e77402420ff7e471bd38cf5ce354a104a194 ``` `bitlisp-asm`, `bitlisp-disasm`, `bitlisp-compile`, and