diff --git a/bip-txhash.md b/bip-txhash.md new file mode 100644 index 0000000000..5bb2e4760e --- /dev/null +++ b/bip-txhash.md @@ -0,0 +1,352 @@ +``` + BIP: tbd + Layer: Consensus (soft fork) + Title: OP_TXHASH and OP_CHECKTXHASHVERIFY + Author: Steven Roose + Comments-URI: https://github.com/bitcoin/bips/wiki/Comments:BIP-tbd + Status: Draft + Type: Standards Track + Created: 2023-09-03 + License: BSD-3-Clause +``` + +# Abstract + +This BIP proposes two new opcodes, `OP_CHECKTXHASHVERIFY`, to be activated +as a change to the semantics of `OP_NOP4` in legacy script, segwit and tapscript; +and OP_TXHASH, to be activated as a change to the semantics of `OP_SUCCESS189` +in tapscript only. + +These opcodes provide a generalized method for introspecting certain details of +the spending transaction, which enables non-interactive enforcement of certain +properties of the transaction spending a certain UTXO. + +The constructions specified in this BIP also open up the way for other +potential updates; see Motivation section for more details. + + +# Summary + +## OP_CHECKTXHASHVERIFY + +The first new opcode, `OP_CHECKTXHASHVERIFY`, redefines the `OP_NOP4` opcode (`0xb3`) as a soft fork upgrade. + +It has the following semantics: + +* There is at least one element on the stack, fail otherwise. +* The element on the stack is at least 32 bytes long, fail otherwise. +* The first 32 bytes are interpreted as the TxHash and the remaining suffix bytes specify the TxFieldSelector. +* If the TxFieldSelector is invalid, fail. +* The actual TxHash of the transaction at the current input index, calculated + using the given TxFieldSelector must be equal to the first 32 bytes of the + element on the stack, fail otherwise. + + +## OP_TXHASH + +The second new opcode, `OP_TXHASH`, redefines the `OP_SUCCESS189` tapscript opcode (`0xbd`) as a soft fork upgrade. + +It has the following semantics: + +* There is at least one element on the stack, fail otherwise. +* The element is interpreted as the TxFieldSelector and is popped off the stack. +* If the TxFieldSelector is invalid, fail. +* The 32-byte TxHash of the transaction at the current input index, calculated + using the given TxFieldSelector is pushed onto the stack. + +## TxFieldSelector + +The TxFieldSelector has the following semantics. We will give a brief conceptual +summary, followed by a reference implementation of the CalculateTxHash function. + +* There are two special cases for the TxFieldSelector: + * the empty value, zero bytes long: it is set equal to `TXFS_SPECIAL_TEMPLATE`, + the de-facto default value which means everything except the prevouts and the prevout + scriptPubkeys. + + Special case `TXFS_SPECIAL_TEMPLATE` is 4 bytes long, as follows: + * 1: `TXFS_ALL` + * 2: `TXFS_INPUTS_TEMPLATE | TXFS_OUTPUTS_ALL` + * 3: `TXFS_INOUT_NUMBER | TXFS_INOUT_SELECTION_ALL` + * 4: `TXFS_INOUT_NUMBER | TXFS_INOUT_SELECTION_ALL` + + * the `0x00` byte: it is set equal to `TXFS_SPECIAL_ALL`, which means "ALL" and is primarily + useful to emulate `SIGHASH_ALL` when `OP_TXHASH` is used in combination + with `OP_CHECKSIGFROMSTACK`. + + Special case `TXFS_SPECIAL_ALL` is 4 bytes long, as follows: + * 1: `TXFS_ALL` + * 2: `TXFS_INPUTS_ALL | TXFS_OUTPUTS_ALL` + * 3: `TXFS_INOUT_NUMBER | TXFS_INOUT_SELECTION_ALL` + * 4: `TXFS_INOUT_NUMBER | TXFS_INOUT_SELECTION_ALL` + +* The first byte of the TxFieldSelector has its 8 bits assigned as follows, from lowest to highest: + * 1: version (`TXFS_VERSION`) + * 2: locktime (`TXFS_LOCKTIME`) + * 3: current input index (`TXFS_CURRENT_INPUT_IDX`) + * 4: current input control block (or empty) (`TXFS_CURRENT_INPUT_CONTROL_BLOCK`) + * 5: current input spent script (i.e. witness script or tapscript) (`TXFS_CURRENT_INPUT_SPENTSCRIPT`) + * 6: current script last `OP_CODESEPARATOR` position (or 0xffffffff) + (`TXFS_CURRENT_INPUT_LAST_CODESEPARATOR_POS`) + * 7: (unused) + * 8: `TXFS_CONTROL` (i.e. include TxFieldSelector into hash) + +* The highest bit of the first byte (`TXFS_CONTROL`), we will call the + "control bit", and it can be used to control the behavior of the opcode. For + `OP_TXHASH` and `OP_CHECKTXHASHVERIFY`, the control bit is used to determine + whether the TxFieldSelector itself has to be included in the resulting hash. + (For potential other uses of the TxFieldSelector (like a hypothetical + `OP_TX`), this bit can be repurposed.) + +* The second byte will be used to indicate fields from the inputs and outputs. + If there is only a single byte present, no information from the inputs and + outputs will be committed. Otherwise, of the second byte, the 8 bits are + assigned the following variables, from lowest to highest: + * Specifying which fields of the inputs will be selected: + * 1: prevouts (`TXFS_INPUTS_PREVOUTS`) + * 2: sequences (`TXFS_INPUTS_SEQUENCES`) + * 3: scriptSigs (`TXFS_INPUTS_SCRIPTSIGS`) + * 4: prevout scriptPubkeys (`TXFS_INPUTS_PREV_SCRIPTPUBKEYS`) + * 5: prevout values (`TXFS_INPUTS_PREV_VALUED`) + * 6: taproot annexes (`TXFS_INPUTS_TAPROOT_ANNEXES`) + + * Specifying which fields of the outputs will be selected: + * 7: scriptPubkeys (`TXFS_OUTPUTS_SCRIPTPUBKEYS`) + * 8: values (`TXFS_OUTPUTS_VALUES`) + +* We define as follows: + * `TXFS_ALL = TXFS_VERSION | TXFS_LOCKTIME | TXFS_CURRENT_INPUT_IDX | TXFS_CURRENT_INPUT_CONTROL_BLOCK | TXFS_CURRENT_INPUT_LAST_CODESEPARATOR_POS | TXFS_INPUTS | TXFS_OUTPUTS | TXFS_CONTROL` + * `TXFS_INPUTS_ALL = TXFS_INPUTS_PREVOUTS | TXFS_INPUTS_SEQUENCES | TXFS_INPUTS_SCRIPTSIGS | TXFS_INPUTS_PREV_SCRIPTPUBKEYS | TXFS_INPUTS_PREV_VALUES | TXFS_INPUTS_TAPROOT_ANNEXES` + * `TXFS_INPUTS_TEMPLATE = TXFS_INPUTS_SEQUENCES | TXFS_INPUTS_SCRIPTSIGS | TXFS_INPUTS_PREV_VALUES | TXFS_INPUTS_TAPROOT_ANNEXES` + * `TXFS_OUTPUTS_ALL = TXFS_OUTPUTS_SCRIPTPUBKEYS | TXFS_OUTPUTS_VALUES` + + +* For both inputs and then outputs, expect an additional byte as follows: + * The highest bit (`TXFS_INOUT_NUMBER`) indicates whether the "number of + in-/outputs" should be committed to. + * For the remaining bits, there are three exceptional values: + * 0x00 (`TXFS_INOUT_SELECTION_NONE`) means "no in/outputs" (hence only the + number of them as `0x80` (`TXFS_INOUT_NUMBER`)). + * `0x40` (`TXFS_INOUT_SELECTION_CURRENT`) means "select only the in/output + of the current input index" (it is invalid when current index exceeds + number of outputs). + * `0x3f` (`TXFS_INOUT_SELECTION_ALL`) means "select all in/outputs". + + * The second highest bit (`TXFS_INOUT_SELECTION_MODE`) is the "specification mode": + * Set to 0 it means "leading mode". + * Set to 1 it means "individual mode". + + * In "leading mode", the third highest bit (`TXFS_INOUT_LEADING_SIZE`) is + used to indicate the "index size", i.e. the number of bytes will be used to + represent the number of in/output. + * With "index size" set to 0, the remaining lowest 5 bits of the first byte + will be interpreted as the number of leading in/outputs to select. + * With "index size" set to 1, the remaining lowest 5 bits of the first byte + together with the 8 bits of the next byte will be interpreted as the + number of leading in/outputs to select. + + * In "individual mode", the third highest bit (`TXFS_INOUT_INDIVIDUAL_MODE`) + indicates whether we are passing absolute indices (0) or indices relative + to the current input (1), the remaining lowest 5 bits will be interpreted + as `n`, the number of individual in/outputs follow. + * In absolute mode (second highest bit is 0), for each of the `n` indices, + at least one extra byte is expected. + * If that byte's highest bit is set to 0, the remaining 7 bits represent + the absolute index to select. + * If that byte's highest bit is set to 1, the remaining 7 bits, together + with the next byte's 8 bits represent the absolute index to select. + * In relative mode (second highest bit is 1), for each of the `n` indices, + at least one extra byte is expected. + * If that byte's highest bit is set to 0, the remaining 7 bits represent + the relative index in two's complement. + * If that byte's highest bit is set to 1, the remaining 7 bits, together + with the next byte's 8 bits represent the relative index in two's + complement. + + +Effectively, this allows a user to select +* all in/outputs +* the current input index +* the leading in/outputs up to 7936 +* up to 32 individually selected in/outputs +** using absolute indices up to 16384 +** using indices relative to the current input index from -8191 to +8192. + +### TxFieldSelector malleability + +It is possible to represent the same selected data using multiple different +TxFieldSelectors. For this reason, users are strongly advised to always set the +`TXFS_CONTROL` that commits to the TxFieldSelector that was used to get the +hash. + + + +### Visualization + +* first byte + +``` +1 0 1 1 1 1 1 1 +| | | | | | | ^ version +| | | | | | ^ locktime +| | | | | ^ current input index +| | | | ^ current input control block +| | | ^ current input spend script +| | ^ current script last OP_CODESEPARATOR +| ^ currently unused +^ control bit (ie. include TXFS in hash) +``` + +* second byte + +``` + v outputs +<-> <---------> inputs +1 1 1 1 1 1 1 1 +| | | | | | | ^ prevouts +| | | | | | ^ sequences +| | | | | ^ scriptSigs +| | | | ^ prevout scriptPubkeys +| | | ^ prevout values +| | ^ taproot annexes +| ^ scriptPubkeys +^ values +``` + +* in/output selector byte + +"only the first 3" +``` +1 0 0 0 0 0 1 1 +| | | <-------> integer 0b00011 == 3 +| | ^ index size 0: single byte +| ^ leading mode +^ commit the number of in/outputs +``` + +"only the first 257" +``` +1 0 1 0 0 0 0 1 0 0 0 0 0 0 0 1 +| | | <------------------------> integer 0b00001 00000001 == 257 +| | ^ index size 1: two bytes +| ^ leading mode +^ commit the number of in/outputs +``` + +"only indices 0 and 2" +``` +0 1 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 1 1 +| | | | <--------------> second idx: 3 +| | | | <--------------> first idx: 1 +| | | | <-----> selection count: 0b10 == 2 +| | | ^ index size 0: single byte per index +| | ^ absolute index +| ^ individual mode +^ don't commit the number of in/outputs +``` + +* total example + +``` +bf ff c2 01 03 83 + | | ^ commit number of outputs + leading 3 outputs + | | <------> commit number of inputs + inputs at indices 1 and 3 + | ^ all input and output fields + ^ all regular fields, except for the unused one +``` + + +## Resource limits + +* For legacy scripts and segwit, we don't add any extra resource limitations, + with the argumentation that `OP_CHECKTXHASHVERIFY` already requires the user + to provide at least 32 bytes of extra transaction size, either in the input + scriptSig, or the witness. Additional more complex hashes require additional + witness bytes. Given that `OP_CAT` is not available in this context, if a + malicious user tries to increase the number of TransactionHashes being + calculated by using opcodes like `OP_DUP`, the TxFieldSelector for all these + calculations is identical, so the calculation can be cached within the same + transaction. + +* For tapscript, primarily motivated by the cheaper opcode `OP_TXHASH` (it + doesn't require an additional 32 witness bytes be provided) and the potential + future addition of byte manipulation opcodes like `OP_CAT`, an additional + cost is specified per TransactionHash execution. Using the same validation + budget ("sigops budget") introduced in BIP-0342, each TransactionHash + decreases the validation budget by 25. If this brings the budget below zero, + the script fails immediately.
The following considerations should be made: + * All fields that can be of arbitrary size are cachable as TransactionHash + always hashes their hashed values. + * In "individual mode", a user can at most commit 32 inputs or outputs, + which we don't consider excessive for potential repeated use. + * In "leading mode", a caching strategy can be used where the SHA256 context + is stored every N in/outputs so that multiple executions of the + TransactionHash function can use the caches and only have to hash an + additional N-1 items at most. + + +# Motivation + +This BIP specifies a basic transaction introspection primitive that is useful +to either reduce interactivity in multi-user protocols or to enforce some basic +constraints on transactions. + +Additionally, the constructions specified in this BIP can lay the groundwork for +some potential future upgrades: +* The TxFieldSelector construction would work well with a hypothetical opcode + `OP_TX` that allows for directly introspecting the transaction by putting the + fields selected on the stack instead of hashing them together. +* The TransactionHash obtained by `OP_TXHASH` can be combined with a + hypothetical opcode `OP_CHECKSIGFROMSTACK` to effectively create an + incredibly flexible signature hash, which would enable constructions like + `SIGHASH_ANYPREVOUT`. + +## Comparing with some alternative proposals + +* This proposal strictly generalizes BIP-119's `OP_CHECKTEMPLATEVERIFY`, as the + default mode of our TxFieldSelector is effectively the same (though not + byte-for-byte identical) as what `OP_CTV` acomplishes, without costing any + additional bytes. Additionally, using `OP_CHECKTXHASHVERIFY` allows for more + flexibility which can help in the case for + * enabling adding fees to a transaction without breaking a multi-tx protocol; + * multi-user protocols where users are only concerned about their own inputs and outputs. + +* Constructions like `OP_IN_OUT_VALUE` used with `OP_EQUALVERIFY` can be + emulated by two `OP_TXHASH` instances by using the TxFieldSelector to select + a single input value first and a single output value second and enforcing + equality on the hashes. Neither of these alternatives can be used to enforce + small value differencials without the availability of 64-bit arithmetic in + Script. + +* Like mentioned above, `SIGHASH_ANYPREVOUT` can be emulated using `OP_TXHASH` + when combined with `OP_CHECKSIGFROMSTACK`: + ` OP_TXHASH OP_CHECKSIGFROMSTACK` effectively emulates `SIGHASH_ANYPREVOUT`. + + +# Detailed Specification + +A reference implementation in Rust is provided attached as part of this BIP +together with a JSON file of test vectors generated using the reference +implementation. + + +# Implementation + +* A proposed implementation for Bitcoin Core is available here: + https://github.com/bitcoin/bitcoin/pull/29050 +* A proposed implementation for rust-bitcoin is available here: + https://github.com/rust-bitcoin/rust-bitcoin/pull/2275 + +Both of the above implementations perform effective caching to avoid potential +denial-of-service attack vectors. + + +# Acknowledgement + +Credit for this proposal mostly goes to Jeremy Rubin for his work on BIP-119's +`OP_CHECKTEMPLATEVERIFY` and to Russell O'Connor for the original idea of +generalizing `OP_CHECKTEMPLATEVERIFY` into `OP_TXHASH`. + +Additional thanks to Andrew Poelstra, Greg Sanders, Rearden Code, Rusty Russell +and others for their feedback on the specification. + diff --git a/bip-txhash/ref-impl/Cargo.toml b/bip-txhash/ref-impl/Cargo.toml new file mode 100644 index 0000000000..05d02e30ff --- /dev/null +++ b/bip-txhash/ref-impl/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "txhash-ref" +version = "0.0.0" +edition = "2021" + +[dependencies] +bitcoin = { version = "=0.31.0", features = [ "serde" ] } +serde_json = "1.0.108" + +# until bitcoin-io is released and https://github.com/rust-bitcoin/rust-bitcoin/pull/2274 is merged +[patch.crates-io] +bitcoin = { git = "https://github.com/stevenroose/rust-bitcoin.git", branch = "txhash", features = [ "serde" ] } +bitcoin_hashes = { git = "https://github.com/stevenroose/rust-bitcoin.git", branch = "txhash" } diff --git a/bip-txhash/ref-impl/src/main.rs b/bip-txhash/ref-impl/src/main.rs new file mode 100644 index 0000000000..8f41d0ce38 --- /dev/null +++ b/bip-txhash/ref-impl/src/main.rs @@ -0,0 +1,652 @@ + +use bitcoin::{Transaction, TxOut}; +use bitcoin::consensus::encode::Encodable; +use bitcoin::hashes::{sha256, Hash, HashEngine}; + +pub const TXFS_VERSION: u8 = 1 << 0; +pub const TXFS_LOCKTIME: u8 = 1 << 1; +pub const TXFS_CURRENT_INPUT_IDX: u8 = 1 << 2; +pub const TXFS_CURRENT_INPUT_SPENTSCRIPT: u8 = 1 << 3; +pub const TXFS_CURRENT_INPUT_CONTROL_BLOCK: u8 = 1 << 4; +pub const TXFS_CURRENT_INPUT_LAST_CODESEPARATOR_POS: u8 = 1 << 5; +// pub const TXFS_UNUSED: u8 = 1 << 6; +pub const TXFS_CONTROL: u8 = 1 << 7; + +pub const TXFS_ALL: u8 = TXFS_VERSION + | TXFS_LOCKTIME + | TXFS_CURRENT_INPUT_IDX + | TXFS_CURRENT_INPUT_SPENTSCRIPT + | TXFS_CURRENT_INPUT_CONTROL_BLOCK + | TXFS_CURRENT_INPUT_LAST_CODESEPARATOR_POS + | TXFS_CONTROL; + +pub const TXFS_INPUTS_PREVOUTS: u8 = 1 << 0; +pub const TXFS_INPUTS_SEQUENCES: u8 = 1 << 1; +pub const TXFS_INPUTS_SCRIPTSIGS: u8 = 1 << 2; +pub const TXFS_INPUTS_PREV_SCRIPTPUBKEYS: u8 = 1 << 3; +pub const TXFS_INPUTS_PREV_VALUES: u8 = 1 << 4; +pub const TXFS_INPUTS_TAPROOT_ANNEXES: u8 = 1 << 5; +pub const TXFS_OUTPUTS_SCRIPTPUBKEYS: u8 = 1 << 6; +pub const TXFS_OUTPUTS_VALUES: u8 = 1 << 7; + +pub const TXFS_INPUTS_ALL: u8 = TXFS_INPUTS_PREVOUTS + | TXFS_INPUTS_SEQUENCES + | TXFS_INPUTS_SCRIPTSIGS + | TXFS_INPUTS_PREV_SCRIPTPUBKEYS + | TXFS_INPUTS_PREV_VALUES + | TXFS_INPUTS_TAPROOT_ANNEXES; +pub const TXFS_INPUTS_TEMPLATE: u8 = TXFS_INPUTS_SEQUENCES + | TXFS_INPUTS_SCRIPTSIGS + | TXFS_INPUTS_PREV_VALUES + | TXFS_INPUTS_TAPROOT_ANNEXES; +pub const TXFS_OUTPUTS_ALL: u8 = TXFS_OUTPUTS_SCRIPTPUBKEYS | TXFS_OUTPUTS_VALUES; + +pub const TXFS_INOUT_NUMBER: u8 = 1 << 7; +pub const TXFS_INOUT_SELECTION_NONE: u8 = 0x00; +pub const TXFS_INOUT_SELECTION_CURRENT: u8 = 0x40; +pub const TXFS_INOUT_SELECTION_ALL: u8 = 0x3f; +pub const TXFS_INOUT_SELECTION_MODE: u8 = 1 << 6; +pub const TXFS_INOUT_LEADING_SIZE: u8 = 1 << 5; +pub const TXFS_INOUT_INDIVIDUAL_MODE: u8 = 1 << 5; +pub const TXFS_INOUT_SELECTION_MASK: u8 = 0xff ^ (1 << 7) ^ (1 << 6) ^ (1 << 5); + + +pub const TXFS_SPECIAL_ALL: [u8; 4] = [ + TXFS_ALL, + TXFS_INPUTS_ALL | TXFS_OUTPUTS_ALL, + TXFS_INOUT_NUMBER | TXFS_INOUT_SELECTION_ALL, + TXFS_INOUT_NUMBER | TXFS_INOUT_SELECTION_ALL, +]; +pub const TXFS_SPECIAL_TEMPLATE: [u8; 4] = [ + TXFS_ALL, + TXFS_INPUTS_TEMPLATE | TXFS_OUTPUTS_ALL, + TXFS_INOUT_NUMBER | TXFS_INOUT_SELECTION_ALL, + TXFS_INOUT_NUMBER | TXFS_INOUT_SELECTION_ALL, +]; + +const SHA256_EMPTY: sha256::Hash = sha256::Hash::const_hash(&[]); + +fn read_i7(input: u8) -> i8 { + let masked = input & 0x7f; + if (masked & 0x40) == 0 { + masked as i8 + } else { + 0i8 - ((!(masked-1)) & 0x7f) as i8 + } +} + +fn read_i15(input: u16) -> i16 { + let masked = input & 0x7fff; + if (masked & 0x4000) == 0 { + masked as i16 + } else { + 0i16 - ((!(masked-1)) & 0x7fff) as i16 + } +} + +/// Parse an input or output selection from the TxFieldSelector bytes. +/// +/// Returns the selected indices and a flag whether to commit the number of items. +fn parse_inout_selection( + bytes: &mut impl Iterator, + nb_items: usize, + current_input_idx: u32, + allow_empty: bool, +) -> Result<(Vec, bool), &'static str> { + let first = match bytes.next() { + Some(b) => b, + None if !allow_empty => return Ok((vec![], false)), + None /* if allow_empty */ => return Err("byte missing instead of empty selection"), + }; + let commit_number = (first & TXFS_INOUT_NUMBER) != 0; + let selection = first & (0xff ^ TXFS_INOUT_NUMBER); + + let selected = if selection == TXFS_INOUT_SELECTION_NONE { + vec![] + } else if selection == TXFS_INOUT_SELECTION_ALL { + (0..nb_items).collect() + } else if selection == TXFS_INOUT_SELECTION_CURRENT { + if current_input_idx as usize >= nb_items { + // NB can only happen for outputs + return Err("current input index exceeds number of outputs and current output selected"); + } + vec![current_input_idx as usize] + } else if (selection & TXFS_INOUT_SELECTION_MODE) == 0 { // leading mode + let count = if (selection & TXFS_INOUT_LEADING_SIZE) == 0 { + (selection & TXFS_INOUT_SELECTION_MASK) as usize + } else { + let next_byte = bytes.next().ok_or("second leading selection byte missing")?; + (((selection & TXFS_INOUT_SELECTION_MASK) as usize) << 8) + next_byte as usize + }; + assert_ne!(count, 0, "this should be interpreted as NONE above"); + if count > nb_items { + return Err("selected number of leading in/outputs out of bounds"); + } + (0..count).collect() + } else { // individual mode + let absolute = (selection & TXFS_INOUT_INDIVIDUAL_MODE) == 0; + + let count = (selection & TXFS_INOUT_SELECTION_MASK) as usize; + + let mut selected = Vec::with_capacity(count as usize); + for _ in 0..count { + let first = bytes.next().ok_or("expected an index byte")?; + let single_byte = (first & (1 << 7)) == 0; + let number = if single_byte { + first as usize + } else { + let next_byte = bytes.next().ok_or("expected another index byte")?; + (((first & (1 << 7)) as usize) << 8) + next_byte as usize + }; + + let idx = if absolute { + number + } else { + let rel = if single_byte { + read_i7(number as u8) as isize + } else { + read_i15(number as u16) as isize + }; + + if rel.is_negative() && rel.abs() > current_input_idx as isize { + return Err("relative index out of bounds"); + } + (current_input_idx as isize + rel) as usize + }; + + if idx > nb_items { + return Err("selected index out of bounds"); + } + if let Some(last) = selected.last() { + if idx <= *last { + return Err("selected indices not in increasing order") + } + } + selected.push(idx); + } + selected + }; + Ok((selected, commit_number)) +} + +/// +/// +/// Assumes that TxFieldSelector is valid. +pub fn calculate_txhash( + txfs: &[u8], + tx: &Transaction, + prevouts: &[TxOut], + current_input_idx: u32, + current_input_last_codeseparator_pos: Option, +) -> Result { + assert_eq!(tx.input.len(), prevouts.len()); + + let txfs = if txfs.is_empty() { + &TXFS_SPECIAL_TEMPLATE + } else if txfs.len() == 1 && txfs[0] == 0x00 { + &TXFS_SPECIAL_ALL + } else { + txfs + }; + + let mut engine = sha256::Hash::engine(); + + if (txfs[0] & TXFS_CONTROL) != 0 { + engine.input(txfs); + } + + let mut bytes = txfs.iter().copied().peekable(); + let global = bytes.next().unwrap(); + + if (global & TXFS_VERSION) != 0 { + tx.version.consensus_encode(&mut engine).unwrap(); + } + + if (global & TXFS_LOCKTIME) != 0 { + tx.lock_time.consensus_encode(&mut engine).unwrap(); + } + + if (global & TXFS_CURRENT_INPUT_IDX) != 0 { + (current_input_idx as u32).consensus_encode(&mut engine).unwrap(); + } + + let cur = current_input_idx as usize; + if (global & TXFS_CURRENT_INPUT_SPENTSCRIPT) != 0 { + let ss = if prevouts[cur].script_pubkey.is_p2sh() { + tx.input[cur].script_sig.redeem_script().map(|s| s.as_bytes()).unwrap_or(&[]) + } else if prevouts[cur].script_pubkey.is_p2wsh() { + tx.input[cur].witness.witness_script().map(|s| s.as_bytes()).unwrap_or(&[]) + } else if prevouts[cur].script_pubkey.is_p2tr() { + tx.input[cur].witness.tapscript().map(|s| s.as_bytes()).unwrap_or(&[]) + } else { + &[] + }; + engine.input(&sha256::Hash::hash(&ss)[..]); + } + + if (global & TXFS_CURRENT_INPUT_CONTROL_BLOCK) != 0 { + let cb = if prevouts[cur].script_pubkey.is_p2tr() { + tx.input[cur].witness.taproot_control_block().unwrap_or(&[]) + } else { + &[] + }; + engine.input(&sha256::Hash::hash(&cb)[..]); + } + + if (global & TXFS_CURRENT_INPUT_LAST_CODESEPARATOR_POS) != 0 { + let pos = current_input_last_codeseparator_pos.unwrap_or(u32::MAX); + (pos as u32).consensus_encode(&mut engine).unwrap(); + } + + let inout_fields = match bytes.next() { + Some(b) => b, + // Stop early if no inputs or outputs are selected. + None => return Ok(sha256::Hash::from_engine(engine)), + }; + + // Inputs + let (input_select, commit_number_inputs) = parse_inout_selection( + &mut bytes, tx.input.len(), current_input_idx, true, + )?; + + if commit_number_inputs { + (tx.input.len() as u32).consensus_encode(&mut engine).unwrap(); + } + + if !input_select.is_empty() && (inout_fields & TXFS_INPUTS_PREVOUTS) != 0 { + let hash = { + let mut engine = sha256::Hash::engine(); + for i in &input_select { + tx.input[*i].previous_output.consensus_encode(&mut engine).unwrap(); + } + sha256::Hash::from_engine(engine) + }; + engine.input(&hash[..]); + } + + if !input_select.is_empty() && (inout_fields & TXFS_INPUTS_SEQUENCES) != 0 { + let hash = { + let mut engine = sha256::Hash::engine(); + for i in &input_select { + tx.input[*i].sequence.consensus_encode(&mut engine).unwrap(); + } + sha256::Hash::from_engine(engine) + }; + engine.input(&hash[..]); + } + + if !input_select.is_empty() && (inout_fields & TXFS_INPUTS_SCRIPTSIGS) != 0 { + let hash = { + let mut engine = sha256::Hash::engine(); + for i in &input_select { + engine.input(&sha256::Hash::hash(&tx.input[*i].script_sig.as_bytes())[..]); + } + sha256::Hash::from_engine(engine) + }; + engine.input(&hash[..]); + } + + if !input_select.is_empty() && (inout_fields & TXFS_INPUTS_PREV_SCRIPTPUBKEYS) != 0 { + let hash = { + let mut engine = sha256::Hash::engine(); + for i in &input_select { + engine.input(&sha256::Hash::hash(&prevouts[*i].script_pubkey.as_bytes())[..]); + } + sha256::Hash::from_engine(engine) + }; + engine.input(&hash[..]); + } + + if !input_select.is_empty() && (inout_fields & TXFS_INPUTS_PREV_VALUES) != 0 { + let hash = { + let mut engine = sha256::Hash::engine(); + for i in &input_select { + prevouts[*i].value.consensus_encode(&mut engine).unwrap(); + } + sha256::Hash::from_engine(engine) + }; + engine.input(&hash[..]); + } + + if !input_select.is_empty() && (inout_fields & TXFS_INPUTS_TAPROOT_ANNEXES) != 0 { + let hash = { + let mut engine = sha256::Hash::engine(); + for i in &input_select { + if prevouts[*i].script_pubkey.is_p2tr() { + if let Some(annex) = tx.input[*i].witness.taproot_annex() { + engine.input(&sha256::Hash::hash(annex)[..]); + } else { + engine.input(&SHA256_EMPTY[..]); + } + } else { + engine.input(&SHA256_EMPTY[..]); + } + } + sha256::Hash::from_engine(engine) + }; + engine.input(&hash[..]); + } + + // Outputs + if bytes.peek().is_none() { + } else { + let allow_empty = (inout_fields & TXFS_OUTPUTS_ALL) == 0; + let (selection, commit_number) = parse_inout_selection( + &mut bytes, tx.output.len(), current_input_idx, allow_empty, + )?; + + if commit_number { + (tx.output.len() as u32).consensus_encode(&mut engine).unwrap(); + } + + if !selection.is_empty() && (inout_fields & TXFS_OUTPUTS_SCRIPTPUBKEYS) != 0 { + let hash = { + let mut engine = sha256::Hash::engine(); + for i in &selection { + engine.input(&sha256::Hash::hash(&tx.output[*i].script_pubkey.as_bytes())[..]); + } + sha256::Hash::from_engine(engine) + }; + hash.consensus_encode(&mut engine).unwrap(); + } + + if !selection.is_empty() && (inout_fields & TXFS_OUTPUTS_VALUES) != 0 { + let hash = { + let mut engine = sha256::Hash::engine(); + for i in &selection { + tx.output[*i].value.consensus_encode(&mut engine).unwrap(); + } + sha256::Hash::from_engine(engine) + }; + hash.consensus_encode(&mut engine).unwrap(); + } + } + + if bytes.next().is_some() { + return Err("unused txfs bytes"); + } + Ok(sha256::Hash::from_engine(engine)) +} + +mod test_vectors { + use super::*; + use std::any::Any; + use std::ops::{self, RangeBounds}; + use bitcoin::hex::DisplayHex; + use bitcoin::{Amount, ScriptBuf, Sequence, Witness}; + use bitcoin::blockdata::transaction::{self, TxIn}; + use bitcoin::opcodes::all::*; + + fn test_vector_tx() -> (Transaction, Vec) { + let tx = Transaction { + version: transaction::Version::TWO, + lock_time: bitcoin::absolute::LockTime::from_consensus(42), + input: vec![ + TxIn { + previous_output: "1111111111111111111111111111111111111111111111111111111111111111:1".parse().unwrap(), + script_sig: vec![0x23].into(), + sequence: Sequence::from_consensus(1), + witness: Witness::new(), + }, + TxIn { + previous_output: "2222222222222222222222222222222222222222222222222222222222222222:2".parse().unwrap(), + script_sig: ScriptBuf::new(), + sequence: Sequence::from_consensus(3), + witness: { // p2wsh annex-like stack element + let mut buf = Witness::new(); + buf.push(vec![0x13]); + buf.push(vec![0x14]); + buf.push(vec![0x50, 0x42]); // annex + buf + }, + }, + TxIn { + previous_output: "3333333333333333333333333333333333333333333333333333333333333333:3".parse().unwrap(), + script_sig: ScriptBuf::new(), + sequence: Sequence::from_consensus(2), + witness: { + let mut buf = Witness::new(); + buf.push(vec![0x12]); + buf + }, + }, + TxIn { + previous_output: "4444444444444444444444444444444444444444444444444444444444444444:4".parse().unwrap(), + script_sig: ScriptBuf::new(), + sequence: Sequence::from_consensus(3), + witness: { + let mut buf = Witness::new(); + buf.push(vec![0x13]); + buf.push(vec![0x14]); + buf.push(vec![0x50, 0x42]); // annex + buf + }, + }, + ], + output: vec![ + TxOut { + script_pubkey: vec![OP_PUSHNUM_6.to_u8()].into(), + value: Amount::from_sat(350), + }, + TxOut { + script_pubkey: vec![OP_PUSHNUM_7.to_u8()].into(), + value: Amount::from_sat(351), + }, + TxOut { + script_pubkey: vec![OP_PUSHNUM_8.to_u8()].into(), + value: Amount::from_sat(353), + }, + ], + }; + let prevs = vec![ + TxOut { + script_pubkey: vec![OP_PUSHNUM_16.to_u8()].into(), + value: Amount::from_sat(360), + }, + TxOut { + script_pubkey: vec![ // p2wsh + 0x00, 0x20, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + ].into(), + value: Amount::from_sat(361), + }, + TxOut { + script_pubkey: vec![ // p2tr + 0x51, 0x20, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + ].into(), + value: Amount::from_sat(361), + }, + TxOut { + script_pubkey: vec![ // p2tr + 0x51, 0x20, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + ].into(), + value: Amount::from_sat(362), + }, + ]; + (tx, prevs) + } + + #[derive(Debug)] + struct TestCase { + tx: Transaction, + prevs: Vec, + vectors: Vec + } + + #[derive(Debug)] + struct TestVector { + txfs: Vec, + input: usize, + codeseparator: Option, + txhash: sha256::Hash, + } + + fn generate_vectors() -> Vec { + let all = TXFS_ALL; + let allio = TXFS_INPUTS_ALL | TXFS_OUTPUTS_ALL; + let selnone = TXFS_INOUT_SELECTION_NONE; // 0x00 + let selcur = TXFS_INOUT_SELECTION_CURRENT; + let selall = TXFS_INOUT_SELECTION_ALL; + let number = TXFS_INOUT_NUMBER; + let leading = 0; + let individual = TXFS_INOUT_SELECTION_MODE; + let absolute = 0; + let relative = TXFS_INOUT_INDIVIDUAL_MODE; + + let nbout = 3; + + fn r + 'static>(t: T) -> Box { + Box::new(t) + } + + // txfs and range of inputs to run it on + let selectors: &[(&[u8], Box)] = &[ + // global + (&[1 << 0], r(..)), + (&[1 << 1], r(..)), + (&[1 << 2], r(..)), + (&[1 << 3], r(..)), + (&[1 << 4], r(..)), + (&[0x9f], r(..)), + // outputs + (&[all, 0, 0, number | selnone], r(..)), + (&[all, TXFS_OUTPUTS_SCRIPTPUBKEYS, 0, selcur], r(..nbout)), + (&[all, TXFS_OUTPUTS_VALUES, 0, selcur], r(..nbout)), + (&[all, TXFS_OUTPUTS_ALL, 0, selcur], r(..nbout)), + (&[all, TXFS_OUTPUTS_SCRIPTPUBKEYS, 0, selall], r(..)), + (&[all, TXFS_OUTPUTS_VALUES, 0, selall], r(..)), + (&[all, TXFS_OUTPUTS_ALL, 0, selall], r(..)), + (&[all, TXFS_OUTPUTS_SCRIPTPUBKEYS, 0, number | selcur], r(..nbout)), + (&[all, TXFS_OUTPUTS_VALUES, 0, number | selcur], r(..nbout)), + (&[all, TXFS_OUTPUTS_ALL, 0, number | selcur], r(..nbout)), + (&[all, TXFS_OUTPUTS_SCRIPTPUBKEYS, 0, number | selall], r(..)), + (&[all, TXFS_OUTPUTS_VALUES, 0, number | selall], r(..)), + (&[all, TXFS_OUTPUTS_ALL, 0, number | selall], r(..)), + // inputs + (&[all, 0, number | selnone], r(..)), + (&[all, TXFS_INPUTS_PREVOUTS, selcur], r(..)), + (&[all, TXFS_INPUTS_SEQUENCES, selcur], r(..)), + (&[all, TXFS_INPUTS_SCRIPTSIGS, selcur], r(..)), + (&[all, TXFS_INPUTS_PREV_SCRIPTPUBKEYS, selcur], r(..)), + (&[all, TXFS_INPUTS_PREV_VALUES, selcur], r(..)), + (&[all, TXFS_INPUTS_TAPROOT_ANNEXES, selcur], r(..)), + (&[all, TXFS_INPUTS_ALL, selcur], r(..)), + (&[all, TXFS_INPUTS_PREVOUTS, selall], r(..)), + (&[all, TXFS_INPUTS_SEQUENCES, selall], r(..)), + (&[all, TXFS_INPUTS_SCRIPTSIGS, selall], r(..)), + (&[all, TXFS_INPUTS_PREV_SCRIPTPUBKEYS, selall], r(..)), + (&[all, TXFS_INPUTS_PREV_VALUES, selall], r(..)), + (&[all, TXFS_INPUTS_TAPROOT_ANNEXES, selall], r(..)), + (&[all, TXFS_INPUTS_ALL, selall], r(..)), + (&[all, TXFS_INPUTS_PREVOUTS, number | selcur], r(..)), + (&[all, TXFS_INPUTS_SEQUENCES, number | selcur], r(..)), + (&[all, TXFS_INPUTS_SCRIPTSIGS, number | selcur], r(..)), + (&[all, TXFS_INPUTS_PREV_SCRIPTPUBKEYS, number | selcur], r(..)), + (&[all, TXFS_INPUTS_PREV_VALUES, number | selcur], r(..)), + (&[all, TXFS_INPUTS_TAPROOT_ANNEXES, number | selcur], r(..)), + (&[all, TXFS_INPUTS_ALL, number | selcur], r(..)), + (&[all, TXFS_INPUTS_PREVOUTS, number | selall], r(..)), + (&[all, TXFS_INPUTS_SEQUENCES, number | selall], r(..)), + (&[all, TXFS_INPUTS_SCRIPTSIGS, number | selall], r(..)), + (&[all, TXFS_INPUTS_PREV_SCRIPTPUBKEYS, number | selall], r(..)), + (&[all, TXFS_INPUTS_PREV_VALUES, number | selall], r(..)), + (&[all, TXFS_INPUTS_TAPROOT_ANNEXES, number | selall], r(..)), + (&[all, TXFS_INPUTS_ALL, number | selall], r(..)), + // both + (&[all, allio, selall, selall], r(..)), + (&[all, allio, selcur, selcur], r(..nbout)), + (&[all, 0, number | selnone, number | selnone], r(..)), + (&[all, allio, number | selall, number | selall], r(..)), + (&[all, allio, number | selcur, number | selcur], r(..nbout)), + (&[all, allio, selcur, selall], r(..)), + (&[all, allio, selall, selcur], r(..nbout)), + // leading + (&[all, allio, leading | 0x01, number | leading | 0x02], r(..)), + (&[all, allio, number | selcur, leading | 0x02], r(..nbout)), + // individual absolute + (&[all, allio, individual | absolute | 0x01, 0x01, + individual | absolute | 0x02, 0x00, 0x02], r(..)), + (&[all, allio, number | individual | absolute | 0x01, 0x01, + number | individual | absolute | 0x02, 0x00, 0x02], r(..)), + // individual relative + (&[all, allio, individual | relative | 0x01, (-1i8 as u8) >> 1, + individual | relative | 0x02, (-1i8 as u8) >> 1, 0], r(1..nbout)), + (&[all, allio, number | individual | relative | 0x01, (-1i8 as u8) >> 1, + number | individual | relative | 0x02, (-1i8 as u8) >> 1, 0], r(1..nbout)), + //TODO(stevenroose) test index size, but for that we need > 32 in/outputs + // special cases + (&[], r(..)), + (&[0x00], r(..)), + ]; + + let cases = vec![ + test_vector_tx(), + ]; + + fn check_range(r: &Box, idx: usize) -> bool { + if let Some(ref range) = r.downcast_ref::() { + return range.contains(&idx); + } + if let Some(ref range) = r.downcast_ref::>() { + return range.contains(&idx); + } + if let Some(ref range) = r.downcast_ref::>() { + return range.contains(&idx); + } + if let Some(ref range) = r.downcast_ref::>() { + return range.contains(&idx); + } + unreachable!("invalid range type used: {:?}", r.type_id()); + } + + cases.into_iter().enumerate().map(|(cidx, (tx, prevs))| { + let mut vectors = Vec::new(); + for (_sidx, (txfs, idx_range)) in selectors.iter().enumerate() { + for i in 0..tx.input.len() { + // println!("{} >> #{} ({}) >> {}", cidx, _sidx, txfs.as_hex(), i); + if !check_range(idx_range, i) { + continue; + } + + match calculate_txhash(txfs, &tx, &prevs, i as u32, None) { + Ok(txhash) => vectors.push(TestVector { + txfs: txfs.to_vec(), + input: i, + codeseparator: None, + txhash: txhash, + }), + Err(e) => panic!("Error in vector #{} for selector {}: {}", + cidx, txfs.as_hex(), e, + ), + } + } + } + TestCase { tx, prevs, vectors } + }).collect() + } + + pub fn write_vector_file(path: impl AsRef) { + use bitcoin::consensus::encode::serialize_hex; + + let ret = generate_vectors().into_iter().enumerate().map(|(i_tx, c)| serde_json::json!({ + "tx": serialize_hex(&c.tx), + "prevs": c.prevs.iter().map(|p| serialize_hex(p)).collect::>(), + "vectors": c.vectors.into_iter().enumerate().map(|(i_v, v)| serde_json::json!({ + "id": format!("{}:{} ({} #{})", i_tx, i_v, v.txfs.as_hex(), v.input), + "txfs": v.txfs.as_hex().to_string(), + "input": v.input, + "codeseparator": v.codeseparator, + "txhash": v.txhash, + })).collect::>(), + })).collect::>(); + + let mut file = std::fs::File::create(path).unwrap(); + serde_json::to_writer_pretty(&mut file, &ret).unwrap(); + } +} + +fn main() { + test_vectors::write_vector_file("./txhash_vectors.json"); +} diff --git a/bip-txhash/ref-impl/txhash_vectors.json b/bip-txhash/ref-impl/txhash_vectors.json new file mode 100644 index 0000000000..4d72808471 --- /dev/null +++ b/bip-txhash/ref-impl/txhash_vectors.json @@ -0,0 +1,1679 @@ +[ + { + "prevs": [ + "68010000000000000160", + "69010000000000002200200100000000000000000000000000000000000000000000000000000000000000", + "69010000000000002251200100000000000000000000000000000000000000000000000000000000000000", + "6a010000000000002251200200000000000000000000000000000000000000000000000000000000000000" + ], + "tx": "02000000000104111111111111111111111111111111111111111111111111111111111111111101000000012301000000222222222222222222222222222222222222222222222222222222222222222202000000000300000033333333333333333333333333333333333333333333333333333333333333330300000000020000004444444444444444444444444444444444444444444444444444444444444444040000000003000000035e0100000000000001565f0100000000000001576101000000000000015800030113011402504201011203011301140250422a000000", + "vectors": [ + { + "codeseparator": null, + "id": "0:0 (01 #0)", + "input": 0, + "txfs": "01", + "txhash": "26b25d457597a7b0463f9620f666dd10aa2c4373a505967c7c8d70922a2d6ece" + }, + { + "codeseparator": null, + "id": "0:1 (01 #1)", + "input": 1, + "txfs": "01", + "txhash": "26b25d457597a7b0463f9620f666dd10aa2c4373a505967c7c8d70922a2d6ece" + }, + { + "codeseparator": null, + "id": "0:2 (01 #2)", + "input": 2, + "txfs": "01", + "txhash": "26b25d457597a7b0463f9620f666dd10aa2c4373a505967c7c8d70922a2d6ece" + }, + { + "codeseparator": null, + "id": "0:3 (01 #3)", + "input": 3, + "txfs": "01", + "txhash": "26b25d457597a7b0463f9620f666dd10aa2c4373a505967c7c8d70922a2d6ece" + }, + { + "codeseparator": null, + "id": "0:4 (02 #0)", + "input": 0, + "txfs": "02", + "txhash": "e8a4b2ee7ede79a3afb332b5b6cc3d952a65fd8cffb897f5d18016577c33d7cc" + }, + { + "codeseparator": null, + "id": "0:5 (02 #1)", + "input": 1, + "txfs": "02", + "txhash": "e8a4b2ee7ede79a3afb332b5b6cc3d952a65fd8cffb897f5d18016577c33d7cc" + }, + { + "codeseparator": null, + "id": "0:6 (02 #2)", + "input": 2, + "txfs": "02", + "txhash": "e8a4b2ee7ede79a3afb332b5b6cc3d952a65fd8cffb897f5d18016577c33d7cc" + }, + { + "codeseparator": null, + "id": "0:7 (02 #3)", + "input": 3, + "txfs": "02", + "txhash": "e8a4b2ee7ede79a3afb332b5b6cc3d952a65fd8cffb897f5d18016577c33d7cc" + }, + { + "codeseparator": null, + "id": "0:8 (04 #0)", + "input": 0, + "txfs": "04", + "txhash": "df3f619804a92fdb4057192dc43dd748ea778adc52bc498ce80524c014b81119" + }, + { + "codeseparator": null, + "id": "0:9 (04 #1)", + "input": 1, + "txfs": "04", + "txhash": "67abdd721024f0ff4e0b3f4c2fc13bc5bad42d0b7851d456d88d203d15aaa450" + }, + { + "codeseparator": null, + "id": "0:10 (04 #2)", + "input": 2, + "txfs": "04", + "txhash": "26b25d457597a7b0463f9620f666dd10aa2c4373a505967c7c8d70922a2d6ece" + }, + { + "codeseparator": null, + "id": "0:11 (04 #3)", + "input": 3, + "txfs": "04", + "txhash": "9d9f290527a6be626a8f5985b26e19b237b44872b03631811df4416fc1713178" + }, + { + "codeseparator": null, + "id": "0:12 (08 #0)", + "input": 0, + "txfs": "08", + "txhash": "5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456" + }, + { + "codeseparator": null, + "id": "0:13 (08 #1)", + "input": 1, + "txfs": "08", + "txhash": "227747766d19539b54f018e7ccfde16bd7c38ebbf5649357ecf67bdfb9755b5c" + }, + { + "codeseparator": null, + "id": "0:14 (08 #2)", + "input": 2, + "txfs": "08", + "txhash": "5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456" + }, + { + "codeseparator": null, + "id": "0:15 (08 #3)", + "input": 3, + "txfs": "08", + "txhash": "58b8e1205472ebed51a76303179ebf44554714af49ef1f78fb4c1a6a795aa3d7" + }, + { + "codeseparator": null, + "id": "0:16 (10 #0)", + "input": 0, + "txfs": "10", + "txhash": "5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456" + }, + { + "codeseparator": null, + "id": "0:17 (10 #1)", + "input": 1, + "txfs": "10", + "txhash": "5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456" + }, + { + "codeseparator": null, + "id": "0:18 (10 #2)", + "input": 2, + "txfs": "10", + "txhash": "5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456" + }, + { + "codeseparator": null, + "id": "0:19 (10 #3)", + "input": 3, + "txfs": "10", + "txhash": "d703d3da6a87bd8e0b453f3b6c41edcc9bf331b2b88ef26eb39dc7abee4e00a3" + }, + { + "codeseparator": null, + "id": "0:20 (9f #0)", + "input": 0, + "txfs": "9f", + "txhash": "788cda528b3d073edd08e076828d446ba83cf55212e55fd67aae0e3cd26da1cf" + }, + { + "codeseparator": null, + "id": "0:21 (9f #1)", + "input": 1, + "txfs": "9f", + "txhash": "c624f4988c251d9b6867549886a456eddb1fbeb06aba97f45a90fc77239b2802" + }, + { + "codeseparator": null, + "id": "0:22 (9f #2)", + "input": 2, + "txfs": "9f", + "txhash": "381bda8b1a75cd5b6fd36fc99709f12aff9039cf6c05d0506384ca7e1cdebf40" + }, + { + "codeseparator": null, + "id": "0:23 (9f #3)", + "input": 3, + "txfs": "9f", + "txhash": "a86927ae6acf2887cd752aaa43ece977b08def610f6a8f10aa812b0f92d41ad7" + }, + { + "codeseparator": null, + "id": "0:24 (bf000080 #0)", + "input": 0, + "txfs": "bf000080", + "txhash": "909743eeacfe89346234ef07de6d565d8cddb2b780feee8f492fecebabebf674" + }, + { + "codeseparator": null, + "id": "0:25 (bf000080 #1)", + "input": 1, + "txfs": "bf000080", + "txhash": "f0c5621484eae42ee887a3de893de7f8807a3b32773b07716d0207da26661d88" + }, + { + "codeseparator": null, + "id": "0:26 (bf000080 #2)", + "input": 2, + "txfs": "bf000080", + "txhash": "cb43c7e232d8025512b2077df18c8ea4c6f0fc22c427adc7c1f26ba7e0ac72ab" + }, + { + "codeseparator": null, + "id": "0:27 (bf000080 #3)", + "input": 3, + "txfs": "bf000080", + "txhash": "85839bb6f128eec0defa1f46592b9ba6225c496f9221ac1fc6c8474efbf9bb2b" + }, + { + "codeseparator": null, + "id": "0:28 (bf400040 #0)", + "input": 0, + "txfs": "bf400040", + "txhash": "cc2f45fb7ae34a4f536a1fcf2ee42c26aae05a6682d62b8516798b2cc5ad89c3" + }, + { + "codeseparator": null, + "id": "0:29 (bf400040 #1)", + "input": 1, + "txfs": "bf400040", + "txhash": "0545dc92f230c4c1ccd139fad4e35ce58acc5f72a0e6ea052fd9bce36be42a93" + }, + { + "codeseparator": null, + "id": "0:30 (bf400040 #2)", + "input": 2, + "txfs": "bf400040", + "txhash": "e5e7e82c2bc2e4989445937daa9b9fe709c8c200030a266e468577882b667fb7" + }, + { + "codeseparator": null, + "id": "0:31 (bf800040 #0)", + "input": 0, + "txfs": "bf800040", + "txhash": "838c86478190b2002cb1d70f59f7eb6f9d5e82f8b40a5059a8629ac9f5f2bd0a" + }, + { + "codeseparator": null, + "id": "0:32 (bf800040 #1)", + "input": 1, + "txfs": "bf800040", + "txhash": "97d7cd7b16074fff38a7e0e4b401fe837374f0c11bb9fbc73cb15622bddbb0ab" + }, + { + "codeseparator": null, + "id": "0:33 (bf800040 #2)", + "input": 2, + "txfs": "bf800040", + "txhash": "d2fa000558748e8f5c5ebd210e5128e2ea9090f2be8fc8a12584ee7869d8d0e7" + }, + { + "codeseparator": null, + "id": "0:34 (bfc00040 #0)", + "input": 0, + "txfs": "bfc00040", + "txhash": "7e7858af5dc394cd72aba8e51e3638d31aec59cad2b370d5d40210d0a0e4d708" + }, + { + "codeseparator": null, + "id": "0:35 (bfc00040 #1)", + "input": 1, + "txfs": "bfc00040", + "txhash": "0af83972c6f97226ade002e02a70e99bd4f339c702edd8d4b0a74a03a3e15ec8" + }, + { + "codeseparator": null, + "id": "0:36 (bfc00040 #2)", + "input": 2, + "txfs": "bfc00040", + "txhash": "7b664689a999678af52be2c71a89f5900289a8fbf7a8f9c46cee462ea5b7a0b9" + }, + { + "codeseparator": null, + "id": "0:37 (bf40003f #0)", + "input": 0, + "txfs": "bf40003f", + "txhash": "5a62d857b3509ae3fdf9380aa34aac830e469f909553535ff0735c180c7a8942" + }, + { + "codeseparator": null, + "id": "0:38 (bf40003f #1)", + "input": 1, + "txfs": "bf40003f", + "txhash": "fd0c43276fb662774cc6bd48736e0cd80b77a9dfd289fce8124f66c4eedc0e16" + }, + { + "codeseparator": null, + "id": "0:39 (bf40003f #2)", + "input": 2, + "txfs": "bf40003f", + "txhash": "d060199991a027da98326d292d2fe0ff79f4453fccb2f06843d6aa00f10254b0" + }, + { + "codeseparator": null, + "id": "0:40 (bf40003f #3)", + "input": 3, + "txfs": "bf40003f", + "txhash": "4825fe58227df79896f8d8b7dcb4c6f9d84e33e28f779e51753ac645c7fe4413" + }, + { + "codeseparator": null, + "id": "0:41 (bf80003f #0)", + "input": 0, + "txfs": "bf80003f", + "txhash": "24a648db751ffc8397d9bab0323c1a21056a4ce551e82a8863a2e66d13fd9beb" + }, + { + "codeseparator": null, + "id": "0:42 (bf80003f #1)", + "input": 1, + "txfs": "bf80003f", + "txhash": "63b2eae798604ee1906a6729d12b2fd2b0fc148cfde58876189359a0642313ad" + }, + { + "codeseparator": null, + "id": "0:43 (bf80003f #2)", + "input": 2, + "txfs": "bf80003f", + "txhash": "89e12f47147821b36da2580c11e979b71bc174b2e914b22992a8b2b5419fe4be" + }, + { + "codeseparator": null, + "id": "0:44 (bf80003f #3)", + "input": 3, + "txfs": "bf80003f", + "txhash": "cd084dadb8290ae5ca4340d2cf4c2e4efb6604ed80d6b3456a5d7ef4c30dc48c" + }, + { + "codeseparator": null, + "id": "0:45 (bfc0003f #0)", + "input": 0, + "txfs": "bfc0003f", + "txhash": "4be49f8fb6648f8a4a9f102402b6cddfd7462e0c825398baed1f83d172c536a3" + }, + { + "codeseparator": null, + "id": "0:46 (bfc0003f #1)", + "input": 1, + "txfs": "bfc0003f", + "txhash": "f9f728de1522010f7c98d3edc1ee981bce965a88d801b31c69e4dc17db62085e" + }, + { + "codeseparator": null, + "id": "0:47 (bfc0003f #2)", + "input": 2, + "txfs": "bfc0003f", + "txhash": "026733f329551cd2a878c71f87dfcc5e3356186a740ded3c7e5f173e9a890c9a" + }, + { + "codeseparator": null, + "id": "0:48 (bfc0003f #3)", + "input": 3, + "txfs": "bfc0003f", + "txhash": "01fb1414468a6bb0f418f3025c79a2991fb982a2f3cd692fa5a367444b617a05" + }, + { + "codeseparator": null, + "id": "0:49 (bf4000c0 #0)", + "input": 0, + "txfs": "bf4000c0", + "txhash": "320ac7fc3f65b98ac24f26c621a525fd6ac40bfdea4642bee57df6b455d4f0bb" + }, + { + "codeseparator": null, + "id": "0:50 (bf4000c0 #1)", + "input": 1, + "txfs": "bf4000c0", + "txhash": "00d5341c01069603bda12f8c774ca750ae4a4943599b4bed80db4ba7fa098c9e" + }, + { + "codeseparator": null, + "id": "0:51 (bf4000c0 #2)", + "input": 2, + "txfs": "bf4000c0", + "txhash": "bab1c4fdb6e5ec8f0bb212a7ca689f894b32a9131ed87a9f6914062b977ecf9f" + }, + { + "codeseparator": null, + "id": "0:52 (bf8000c0 #0)", + "input": 0, + "txfs": "bf8000c0", + "txhash": "24b52d7eccd89a67d6dd53d4c7926b623805b63f89d79ff6ec9c074e4bfd0fca" + }, + { + "codeseparator": null, + "id": "0:53 (bf8000c0 #1)", + "input": 1, + "txfs": "bf8000c0", + "txhash": "1742194ed59106637bacd13fb741207b79218842f30a56a5bc51fd3ad07690b4" + }, + { + "codeseparator": null, + "id": "0:54 (bf8000c0 #2)", + "input": 2, + "txfs": "bf8000c0", + "txhash": "4ef58962ccf9e73e700f220fb36d9efc7453f2a85750fe60e54e8b54103bce06" + }, + { + "codeseparator": null, + "id": "0:55 (bfc000c0 #0)", + "input": 0, + "txfs": "bfc000c0", + "txhash": "be26ea04357ad58dab384e9056f44ea2fd1215ca45ac6a8e6e074751e10bb8b1" + }, + { + "codeseparator": null, + "id": "0:56 (bfc000c0 #1)", + "input": 1, + "txfs": "bfc000c0", + "txhash": "8adca9ef3c5478df8e922fdb07df427be866c81dd781bf62e3f8740a48486ece" + }, + { + "codeseparator": null, + "id": "0:57 (bfc000c0 #2)", + "input": 2, + "txfs": "bfc000c0", + "txhash": "fa735aa77734ee736a3b87869aab1bc549fee5e6700abe49f4c1d37f21b9b8fb" + }, + { + "codeseparator": null, + "id": "0:58 (bf4000bf #0)", + "input": 0, + "txfs": "bf4000bf", + "txhash": "a857fa3a369230319af68871b7708a67011bd6ca2a911a75db952e9f9d038dc7" + }, + { + "codeseparator": null, + "id": "0:59 (bf4000bf #1)", + "input": 1, + "txfs": "bf4000bf", + "txhash": "29c8b0dcc430e6040ca399420f3af860038c68a6dd815dcacd4d038117e49fb1" + }, + { + "codeseparator": null, + "id": "0:60 (bf4000bf #2)", + "input": 2, + "txfs": "bf4000bf", + "txhash": "03fd5deab0ed07cc4ec63c5467196e43c03d5e9ab4dc37f9990fd1251e61b07a" + }, + { + "codeseparator": null, + "id": "0:61 (bf4000bf #3)", + "input": 3, + "txfs": "bf4000bf", + "txhash": "bd64c8c01ecf01f8f0f6221a16f946c9c237f8a9666049c181860c8b2e349eaa" + }, + { + "codeseparator": null, + "id": "0:62 (bf8000bf #0)", + "input": 0, + "txfs": "bf8000bf", + "txhash": "94cadfaeb853225d55ab5179661052e98c8ea5b459f35823f0860347feb4ca09" + }, + { + "codeseparator": null, + "id": "0:63 (bf8000bf #1)", + "input": 1, + "txfs": "bf8000bf", + "txhash": "f62e5ce4a5454a7cb2f1dcca724c7db76135a7d63d59408a7563845e3234df9d" + }, + { + "codeseparator": null, + "id": "0:64 (bf8000bf #2)", + "input": 2, + "txfs": "bf8000bf", + "txhash": "67e24cfb5ffbe4687814804ed65bb425e87da50d6c552ff2387d5a01c17d934a" + }, + { + "codeseparator": null, + "id": "0:65 (bf8000bf #3)", + "input": 3, + "txfs": "bf8000bf", + "txhash": "d4d524ad1f8f0def280ad995a96d47b457584dab4f98d0af18c0861fb3ddffaa" + }, + { + "codeseparator": null, + "id": "0:66 (bfc000bf #0)", + "input": 0, + "txfs": "bfc000bf", + "txhash": "46e767c84c7a5725c0fa2634e2fbe3d639f99fee30740100c825ed15a1c93054" + }, + { + "codeseparator": null, + "id": "0:67 (bfc000bf #1)", + "input": 1, + "txfs": "bfc000bf", + "txhash": "f4f16538753838051a53dbe298ad0a7b6eed217f4f28e43ebf5e6dd70fc2e9a3" + }, + { + "codeseparator": null, + "id": "0:68 (bfc000bf #2)", + "input": 2, + "txfs": "bfc000bf", + "txhash": "e6c44b23e1c89684428649dd7914bb85f1401ea33dd9dcb43d38bff58e4d165c" + }, + { + "codeseparator": null, + "id": "0:69 (bfc000bf #3)", + "input": 3, + "txfs": "bfc000bf", + "txhash": "5478d266606667fbb082cf4cc873ac0a19a26fb2e6d1792b1f1efc187996beb1" + }, + { + "codeseparator": null, + "id": "0:70 (bf0080 #0)", + "input": 0, + "txfs": "bf0080", + "txhash": "98099573d0c8acf2412a56d00ccccb3a824bbd338aa2e71015d12ab4e65a308a" + }, + { + "codeseparator": null, + "id": "0:71 (bf0080 #1)", + "input": 1, + "txfs": "bf0080", + "txhash": "11262a337760e5288d3575755164cde0680e98e3d7541d428c2b04f186dc08c0" + }, + { + "codeseparator": null, + "id": "0:72 (bf0080 #2)", + "input": 2, + "txfs": "bf0080", + "txhash": "5ce7cb1c7fb43e49f189912cba730679f7e980d47d6c53237709d3396e20f564" + }, + { + "codeseparator": null, + "id": "0:73 (bf0080 #3)", + "input": 3, + "txfs": "bf0080", + "txhash": "b9ead7c42c8b3f46cd714c7b60a62dc782b88ad70ef19d6cb091d3400b434671" + }, + { + "codeseparator": null, + "id": "0:74 (bf0140 #0)", + "input": 0, + "txfs": "bf0140", + "txhash": "5e7f1ccc9daa9a41341c1301f86d9398a5db8276e49c6e080c2ba1fc4def8417" + }, + { + "codeseparator": null, + "id": "0:75 (bf0140 #1)", + "input": 1, + "txfs": "bf0140", + "txhash": "49dc0f501b33e22278435c0d67d2c90fadba264ca87d9eef9d1c758efbc8bdab" + }, + { + "codeseparator": null, + "id": "0:76 (bf0140 #2)", + "input": 2, + "txfs": "bf0140", + "txhash": "ddb7d118d80696bfa08dfa5c614d33bf39c6acc597b5b7ef34bf23093bde38db" + }, + { + "codeseparator": null, + "id": "0:77 (bf0140 #3)", + "input": 3, + "txfs": "bf0140", + "txhash": "a71c925f68219cb60a879dc7f2cd5c55ed029077569e46f96e027bafb9004e5c" + }, + { + "codeseparator": null, + "id": "0:78 (bf0240 #0)", + "input": 0, + "txfs": "bf0240", + "txhash": "26a5974378ef2d4d876bf25722dd83c40449180a92fd914dc6022e55891a57d8" + }, + { + "codeseparator": null, + "id": "0:79 (bf0240 #1)", + "input": 1, + "txfs": "bf0240", + "txhash": "72eff37a7185242e47f184d3f14ed6d6a3e79643b35d416b78893ed0de4bc8e7" + }, + { + "codeseparator": null, + "id": "0:80 (bf0240 #2)", + "input": 2, + "txfs": "bf0240", + "txhash": "4712a28e5d7a775679fd0fd092ee807685d276bd31c84a3c7cec7ea01b5d9d61" + }, + { + "codeseparator": null, + "id": "0:81 (bf0240 #3)", + "input": 3, + "txfs": "bf0240", + "txhash": "55910ced9d5b405fd23456c8ba7cd8726f769d8dbf04b41764eaffa9854e02e9" + }, + { + "codeseparator": null, + "id": "0:82 (bf0440 #0)", + "input": 0, + "txfs": "bf0440", + "txhash": "bc0e0f1d960653ba38897859c2d547a214c259811178459c616d301c7e84e193" + }, + { + "codeseparator": null, + "id": "0:83 (bf0440 #1)", + "input": 1, + "txfs": "bf0440", + "txhash": "21f224d3a1b46d6dba88629912d881d1f5282c4f0f2159d9972086b20afaa661" + }, + { + "codeseparator": null, + "id": "0:84 (bf0440 #2)", + "input": 2, + "txfs": "bf0440", + "txhash": "a81748740b6ee92fe80c18bcb861bcd760644d189e32a2ebbb38806c1fbc7a88" + }, + { + "codeseparator": null, + "id": "0:85 (bf0440 #3)", + "input": 3, + "txfs": "bf0440", + "txhash": "dec9e7680c658395ca2b70c77d072fbe79f90d49d147497d77983d46dd6cfa69" + }, + { + "codeseparator": null, + "id": "0:86 (bf0840 #0)", + "input": 0, + "txfs": "bf0840", + "txhash": "2c63aeb94ce9efe3274c6b627d3b3aece1a63fafd88fe166891fc0489a28921d" + }, + { + "codeseparator": null, + "id": "0:87 (bf0840 #1)", + "input": 1, + "txfs": "bf0840", + "txhash": "c50717ebf3809b46a1c6699187cc63f3f0e3623e1740d44a08aab35102482bc4" + }, + { + "codeseparator": null, + "id": "0:88 (bf0840 #2)", + "input": 2, + "txfs": "bf0840", + "txhash": "b3fdfb77fb2753960369edf1cd2760cceb431dc7c358228c304d142061f05312" + }, + { + "codeseparator": null, + "id": "0:89 (bf0840 #3)", + "input": 3, + "txfs": "bf0840", + "txhash": "69a3b36bfb519c5cbdafb7b9d1a2617a5b190b5bcf7afbb479ff0a392e0a7349" + }, + { + "codeseparator": null, + "id": "0:90 (bf1040 #0)", + "input": 0, + "txfs": "bf1040", + "txhash": "103fde157d4f8a39a8a9fdf53df1369b8ad67e55d0058300e4252ee2f939d8bd" + }, + { + "codeseparator": null, + "id": "0:91 (bf1040 #1)", + "input": 1, + "txfs": "bf1040", + "txhash": "7c5b6a65ef53f14abc2c3cb824ee138062d31f27fc3f064d4125f80ab2877579" + }, + { + "codeseparator": null, + "id": "0:92 (bf1040 #2)", + "input": 2, + "txfs": "bf1040", + "txhash": "c71655fa2fe5e8f97edfcb8d0a610d252c2fe029efc64bca1b022bcdd371c460" + }, + { + "codeseparator": null, + "id": "0:93 (bf1040 #3)", + "input": 3, + "txfs": "bf1040", + "txhash": "be78626e6af36f7e13dd19e979dec9f7bafaf1f942f430f331028120f511fbba" + }, + { + "codeseparator": null, + "id": "0:94 (bf2040 #0)", + "input": 0, + "txfs": "bf2040", + "txhash": "8b8a9c11cb01fcac02d2692741df9075bb82932e098b05930a91e46070b5a2b8" + }, + { + "codeseparator": null, + "id": "0:95 (bf2040 #1)", + "input": 1, + "txfs": "bf2040", + "txhash": "3a690a5dca6a070769a50c186332102978ddbdff52fcb82fe7a33a74400add31" + }, + { + "codeseparator": null, + "id": "0:96 (bf2040 #2)", + "input": 2, + "txfs": "bf2040", + "txhash": "08e06a10f99abf7f53b2ea5e0b20f993787420c3d6871217b7e583530e5f32b9" + }, + { + "codeseparator": null, + "id": "0:97 (bf2040 #3)", + "input": 3, + "txfs": "bf2040", + "txhash": "b6529d7943d188e82a5fd1512c93c5fd6ac0252f79098d3cb04d471a5ccdb452" + }, + { + "codeseparator": null, + "id": "0:98 (bf3f40 #0)", + "input": 0, + "txfs": "bf3f40", + "txhash": "62b46938532bb50b7b8dfa19f155c2066cc4f8138ab7ccbb4f7cb643bd745ae0" + }, + { + "codeseparator": null, + "id": "0:99 (bf3f40 #1)", + "input": 1, + "txfs": "bf3f40", + "txhash": "c69f90f330d6729f654e1cceddb5f852468ceab164772c3d985c6ecde6849899" + }, + { + "codeseparator": null, + "id": "0:100 (bf3f40 #2)", + "input": 2, + "txfs": "bf3f40", + "txhash": "b50fe6e1494b7581ab62f74495371e1856122e643baf002fe83101ae54c2e667" + }, + { + "codeseparator": null, + "id": "0:101 (bf3f40 #3)", + "input": 3, + "txfs": "bf3f40", + "txhash": "405a5f91daaefe617a83efd00482bdc2219620df7507b9f146f8b5ba028946b1" + }, + { + "codeseparator": null, + "id": "0:102 (bf013f #0)", + "input": 0, + "txfs": "bf013f", + "txhash": "a10db52c586a6aee9e6102b220726777fa5bbfcd410949bceef034364a3acdff" + }, + { + "codeseparator": null, + "id": "0:103 (bf013f #1)", + "input": 1, + "txfs": "bf013f", + "txhash": "eb0206e898a977096ee95283e4ebc5812559652fdc2ae3ac024d69cd553eea87" + }, + { + "codeseparator": null, + "id": "0:104 (bf013f #2)", + "input": 2, + "txfs": "bf013f", + "txhash": "29d20f8ebd591394c41abcac676d7ae0e6d8985201d00004cf2705ff8071bc1a" + }, + { + "codeseparator": null, + "id": "0:105 (bf013f #3)", + "input": 3, + "txfs": "bf013f", + "txhash": "88f4156cb13e8b42a551dbdaa943d2b489c637f414207dca61a52077cbe4324f" + }, + { + "codeseparator": null, + "id": "0:106 (bf023f #0)", + "input": 0, + "txfs": "bf023f", + "txhash": "9d6ae6a8acae0d6f103ebc84aeb782d16de96d31619b64f7c997fbe52fe8c437" + }, + { + "codeseparator": null, + "id": "0:107 (bf023f #1)", + "input": 1, + "txfs": "bf023f", + "txhash": "4eae0eea63bb071811b0d7db65ffdb21befada00f3c7b63bcf966b462b5d6a6c" + }, + { + "codeseparator": null, + "id": "0:108 (bf023f #2)", + "input": 2, + "txfs": "bf023f", + "txhash": "a422efd98ec2f6b3d99ce3fbb2b333bc56914f1b9800e4c7b6865aec9de3ac8c" + }, + { + "codeseparator": null, + "id": "0:109 (bf023f #3)", + "input": 3, + "txfs": "bf023f", + "txhash": "3ed241395d201889d5038303451be81961af39ce22458c1b330f39511742870e" + }, + { + "codeseparator": null, + "id": "0:110 (bf043f #0)", + "input": 0, + "txfs": "bf043f", + "txhash": "b5690bbdf246eed4e9637035446d9ce3e70506c6da4df81d1902f8696e20302e" + }, + { + "codeseparator": null, + "id": "0:111 (bf043f #1)", + "input": 1, + "txfs": "bf043f", + "txhash": "1c5ba6240885fc6ac83d51eb9dc2b1e65866e12df1a486bb43e9bb8a4913fdde" + }, + { + "codeseparator": null, + "id": "0:112 (bf043f #2)", + "input": 2, + "txfs": "bf043f", + "txhash": "373d9ad97ac012472d6c9ef12cf9572f309e81fc4274615f3959b8bf68bace2e" + }, + { + "codeseparator": null, + "id": "0:113 (bf043f #3)", + "input": 3, + "txfs": "bf043f", + "txhash": "c0ad2b14dca838cd9f49c41ec61b08edd6c32c400dfe707377b4f0a1b540ac73" + }, + { + "codeseparator": null, + "id": "0:114 (bf083f #0)", + "input": 0, + "txfs": "bf083f", + "txhash": "df10b44dd8bb7eea80704941d96e8dcda57a4237c385e6afef129313020ea4eb" + }, + { + "codeseparator": null, + "id": "0:115 (bf083f #1)", + "input": 1, + "txfs": "bf083f", + "txhash": "ea971784d31c7bfe4bfb8c9eaf4a79d64ca281086c2120b41ed0992faef7d015" + }, + { + "codeseparator": null, + "id": "0:116 (bf083f #2)", + "input": 2, + "txfs": "bf083f", + "txhash": "ad45cf7e636e2157e7ea0946785e4ae4f06a194bd78675e9f164e0d23776095b" + }, + { + "codeseparator": null, + "id": "0:117 (bf083f #3)", + "input": 3, + "txfs": "bf083f", + "txhash": "2cd38bb04853b7b5ead4bc6c2ccd45d8565d3bf366c360602f681c82f1473834" + }, + { + "codeseparator": null, + "id": "0:118 (bf103f #0)", + "input": 0, + "txfs": "bf103f", + "txhash": "d3d206eb5bfcaad0c1f7ea33f7d17bfd5b51c82ab104de00c2bc968a03fe2f1c" + }, + { + "codeseparator": null, + "id": "0:119 (bf103f #1)", + "input": 1, + "txfs": "bf103f", + "txhash": "832701794b4cae9afec64b5fda02c1e06a89de7539c4ccd70c32db19c4420a05" + }, + { + "codeseparator": null, + "id": "0:120 (bf103f #2)", + "input": 2, + "txfs": "bf103f", + "txhash": "c2dfa9f5c46d1a2e7fecf7bfd9495e494b0f55aa99aa02beeab0eeadba2c243d" + }, + { + "codeseparator": null, + "id": "0:121 (bf103f #3)", + "input": 3, + "txfs": "bf103f", + "txhash": "ce5973996dee00456d723e39e63beeeaf2dd1266a0744bed81120ab002e8401c" + }, + { + "codeseparator": null, + "id": "0:122 (bf203f #0)", + "input": 0, + "txfs": "bf203f", + "txhash": "fb371243b7f09a6d0cdf60f8e7c94375f5b25ae47a5090f0a310de977ae3fc94" + }, + { + "codeseparator": null, + "id": "0:123 (bf203f #1)", + "input": 1, + "txfs": "bf203f", + "txhash": "5112347c861514ae312130ed00ec7d7ac4febc5bc1e1c8e665568d02e24bbe89" + }, + { + "codeseparator": null, + "id": "0:124 (bf203f #2)", + "input": 2, + "txfs": "bf203f", + "txhash": "d3a4b8d449861b7391b084e1156fedd4402c8e6e6892e5f80cb4519bdf404ce3" + }, + { + "codeseparator": null, + "id": "0:125 (bf203f #3)", + "input": 3, + "txfs": "bf203f", + "txhash": "ca878a865f411e4a0975b9e825877bd66a3ee1ca31c1bb68277aacd4763b6c37" + }, + { + "codeseparator": null, + "id": "0:126 (bf3f3f #0)", + "input": 0, + "txfs": "bf3f3f", + "txhash": "5110b06a0372f39037991c5c397be5f51917650022689cc127a0c344e9aea025" + }, + { + "codeseparator": null, + "id": "0:127 (bf3f3f #1)", + "input": 1, + "txfs": "bf3f3f", + "txhash": "31c960f9b2d9ee892043ee348917e78d50e87c42e3a199792ae5b43cb17063c9" + }, + { + "codeseparator": null, + "id": "0:128 (bf3f3f #2)", + "input": 2, + "txfs": "bf3f3f", + "txhash": "29931e33cfdf36fc120990f21528d8000c847cf2d0d6b290c9a2a90aaa559827" + }, + { + "codeseparator": null, + "id": "0:129 (bf3f3f #3)", + "input": 3, + "txfs": "bf3f3f", + "txhash": "70526710c2a21a8cdac91e71927477a3340af535cfd2ac78ac440525d67f08a3" + }, + { + "codeseparator": null, + "id": "0:130 (bf01c0 #0)", + "input": 0, + "txfs": "bf01c0", + "txhash": "e27f8403f4962e7324799a6ab6d13793c6fbd9b1dcd1abb6e1ec58de74eb9dab" + }, + { + "codeseparator": null, + "id": "0:131 (bf01c0 #1)", + "input": 1, + "txfs": "bf01c0", + "txhash": "8569d6fc9a0df3eb0fa19716da6a0e1862d557848f3cc831cc950468c6e025ad" + }, + { + "codeseparator": null, + "id": "0:132 (bf01c0 #2)", + "input": 2, + "txfs": "bf01c0", + "txhash": "48b2978794a8d67f1aa905a57ee192c6d171c2b11e863b5ff4383ef6f3885b01" + }, + { + "codeseparator": null, + "id": "0:133 (bf01c0 #3)", + "input": 3, + "txfs": "bf01c0", + "txhash": "f4c2b7d35210255d398d0a0bc140b2a2764e88a8a45fa49303079d69773b61a8" + }, + { + "codeseparator": null, + "id": "0:134 (bf02c0 #0)", + "input": 0, + "txfs": "bf02c0", + "txhash": "64b349c2b6a89f517a2d8b2de32648ecd1d9abada58db2c1d583d7d565135dad" + }, + { + "codeseparator": null, + "id": "0:135 (bf02c0 #1)", + "input": 1, + "txfs": "bf02c0", + "txhash": "531ae40c0a98ee56dc5bf388023254c6ed8c267e8b13531b629b7da721723b1e" + }, + { + "codeseparator": null, + "id": "0:136 (bf02c0 #2)", + "input": 2, + "txfs": "bf02c0", + "txhash": "cdff9a58a95eaca822ae13198bde7df62468194b287e1fc63825f3beab54617e" + }, + { + "codeseparator": null, + "id": "0:137 (bf02c0 #3)", + "input": 3, + "txfs": "bf02c0", + "txhash": "ef374acb1c23ffff8102294a8e289199bf8948ab18d52d43756d127fd29081e4" + }, + { + "codeseparator": null, + "id": "0:138 (bf04c0 #0)", + "input": 0, + "txfs": "bf04c0", + "txhash": "f644362b941e62dbdd044c3b8bd7ab5ef494efafb99a1f05a04b02445d448ea1" + }, + { + "codeseparator": null, + "id": "0:139 (bf04c0 #1)", + "input": 1, + "txfs": "bf04c0", + "txhash": "88b716e88fa0f9e12b4c8556f29625c7352c946c78cf342ddb5588fa9287126d" + }, + { + "codeseparator": null, + "id": "0:140 (bf04c0 #2)", + "input": 2, + "txfs": "bf04c0", + "txhash": "188e7b1ab08e26959d5738989bbaa4c50e8010fe031853a6d348ebac768ad447" + }, + { + "codeseparator": null, + "id": "0:141 (bf04c0 #3)", + "input": 3, + "txfs": "bf04c0", + "txhash": "abe4b758dec4b8deb33327f12de2fb60905eb2750584ae3e81e641a359542a85" + }, + { + "codeseparator": null, + "id": "0:142 (bf08c0 #0)", + "input": 0, + "txfs": "bf08c0", + "txhash": "273358e4201e28721f9c8408eae617fe8919eb3b815c909e50863258311c3338" + }, + { + "codeseparator": null, + "id": "0:143 (bf08c0 #1)", + "input": 1, + "txfs": "bf08c0", + "txhash": "3d4f4e9fb10b24194dbeea548ee0c803e430b8ece32fd6da1769e8fde4b1e38e" + }, + { + "codeseparator": null, + "id": "0:144 (bf08c0 #2)", + "input": 2, + "txfs": "bf08c0", + "txhash": "9346f4afd1b08b945effb9db026ab658c1ba3e4e6785433ecba957b491601cee" + }, + { + "codeseparator": null, + "id": "0:145 (bf08c0 #3)", + "input": 3, + "txfs": "bf08c0", + "txhash": "e083483af63a4b8cb9498b192e660852ee28a1a5170f31d48b4fefb998df3119" + }, + { + "codeseparator": null, + "id": "0:146 (bf10c0 #0)", + "input": 0, + "txfs": "bf10c0", + "txhash": "201faca1e41f7095decf06f94f2132755874cc7b918c1768eba1de9ea507cd7c" + }, + { + "codeseparator": null, + "id": "0:147 (bf10c0 #1)", + "input": 1, + "txfs": "bf10c0", + "txhash": "46a41197c242b275e780cf322b4b2ccf6790d928a110461bd4077db6492c2283" + }, + { + "codeseparator": null, + "id": "0:148 (bf10c0 #2)", + "input": 2, + "txfs": "bf10c0", + "txhash": "759a5cf343b3e47a2b12a0ead8a05ac5f4ec3e4814c6b78e3a1b00eff3eea5d5" + }, + { + "codeseparator": null, + "id": "0:149 (bf10c0 #3)", + "input": 3, + "txfs": "bf10c0", + "txhash": "5964ef13cb2407787c2fd686bfff78062312bb5bb1a81cda6421253108911cff" + }, + { + "codeseparator": null, + "id": "0:150 (bf20c0 #0)", + "input": 0, + "txfs": "bf20c0", + "txhash": "8bc4316796e69b25abac010e5ae95378c44b8a522996a2f16369f8a0ed869481" + }, + { + "codeseparator": null, + "id": "0:151 (bf20c0 #1)", + "input": 1, + "txfs": "bf20c0", + "txhash": "36e78973ab9294b4248371950cc064e6debd5501c3b4403e22e4dccf3d0be79d" + }, + { + "codeseparator": null, + "id": "0:152 (bf20c0 #2)", + "input": 2, + "txfs": "bf20c0", + "txhash": "4224316625430210c4f8b0c20b6648abea7cedf7bbac7eacfa7312d0c471e913" + }, + { + "codeseparator": null, + "id": "0:153 (bf20c0 #3)", + "input": 3, + "txfs": "bf20c0", + "txhash": "5e122b44de968638acbee647f4bdf47d79e4064cacf944530762a2efb6a0bf65" + }, + { + "codeseparator": null, + "id": "0:154 (bf3fc0 #0)", + "input": 0, + "txfs": "bf3fc0", + "txhash": "3dfec9ecf248ad4dd2bb325e19ae66ff33c7bc63215bfc2bb054cb3e6c70eb3b" + }, + { + "codeseparator": null, + "id": "0:155 (bf3fc0 #1)", + "input": 1, + "txfs": "bf3fc0", + "txhash": "71231c67a7845d61cc63f2899597b21f010a5f776dff5c2d29c6ef92479dba76" + }, + { + "codeseparator": null, + "id": "0:156 (bf3fc0 #2)", + "input": 2, + "txfs": "bf3fc0", + "txhash": "6888b238b7771c4147d9984dcac5b682c0a0d5011160669acd6b71556c78b003" + }, + { + "codeseparator": null, + "id": "0:157 (bf3fc0 #3)", + "input": 3, + "txfs": "bf3fc0", + "txhash": "abf68afb539a35a1257bc4f7c04bc8d9b2882b0b481da1aa3b1c41b1616c4c10" + }, + { + "codeseparator": null, + "id": "0:158 (bf01bf #0)", + "input": 0, + "txfs": "bf01bf", + "txhash": "13e530a826e4dd2863685285be88363007de486343d111a3f12235a7ff8d71a7" + }, + { + "codeseparator": null, + "id": "0:159 (bf01bf #1)", + "input": 1, + "txfs": "bf01bf", + "txhash": "9764affaf72185926e2b7611192e98036c520776a4a6181021de622d2de4b04d" + }, + { + "codeseparator": null, + "id": "0:160 (bf01bf #2)", + "input": 2, + "txfs": "bf01bf", + "txhash": "ce45e8d563bda897093e5ae8dacd82c36253669f63d1ae203bddfea24e4f9c96" + }, + { + "codeseparator": null, + "id": "0:161 (bf01bf #3)", + "input": 3, + "txfs": "bf01bf", + "txhash": "f9dd819633b0f471e84c4bd97cf266eec393e310f73d37b68f2e904199ce2373" + }, + { + "codeseparator": null, + "id": "0:162 (bf02bf #0)", + "input": 0, + "txfs": "bf02bf", + "txhash": "ba05eb61cad20b2ff9664f1b00388fcc17c62b7d90ea2a11775eacd160a37033" + }, + { + "codeseparator": null, + "id": "0:163 (bf02bf #1)", + "input": 1, + "txfs": "bf02bf", + "txhash": "b7d7a181c95271e53970c4ac22f2c7644e0286a94c93dabbff0977611f3b07f6" + }, + { + "codeseparator": null, + "id": "0:164 (bf02bf #2)", + "input": 2, + "txfs": "bf02bf", + "txhash": "2da0277688721236bbbc514027225e19591912c64470468bf676e62980211b3c" + }, + { + "codeseparator": null, + "id": "0:165 (bf02bf #3)", + "input": 3, + "txfs": "bf02bf", + "txhash": "2edc366bb0eb57feca8f7f3779ce92ed142477809b31a101f3cdbb9b21bb102b" + }, + { + "codeseparator": null, + "id": "0:166 (bf04bf #0)", + "input": 0, + "txfs": "bf04bf", + "txhash": "f119b71698363633021266fc8870089cb46b38b66b1d0b7516b10841f78ad793" + }, + { + "codeseparator": null, + "id": "0:167 (bf04bf #1)", + "input": 1, + "txfs": "bf04bf", + "txhash": "a44b938490c8e50f1cb11bc3f19bdb3cafc80b25461d0418a3dd78337cbaae89" + }, + { + "codeseparator": null, + "id": "0:168 (bf04bf #2)", + "input": 2, + "txfs": "bf04bf", + "txhash": "90a1aff219299e352ecf49c9bef2da90285fc8cef88fc5ee31dc642366259e06" + }, + { + "codeseparator": null, + "id": "0:169 (bf04bf #3)", + "input": 3, + "txfs": "bf04bf", + "txhash": "b36106a4096cd747bfa172bd676a17a1fd19af44a2242dd79ae9e1cf6ea41d5e" + }, + { + "codeseparator": null, + "id": "0:170 (bf08bf #0)", + "input": 0, + "txfs": "bf08bf", + "txhash": "071ac3c1db196b98eeaf32935722d063ae37471ab3969643e26aa4d66989b323" + }, + { + "codeseparator": null, + "id": "0:171 (bf08bf #1)", + "input": 1, + "txfs": "bf08bf", + "txhash": "93e73ed5055e0441dd9a731e382662aeb709f430ca5ad8094a154af9167f86de" + }, + { + "codeseparator": null, + "id": "0:172 (bf08bf #2)", + "input": 2, + "txfs": "bf08bf", + "txhash": "e4f74ea7bec7ce29a2f1cc53702c43ddc219509d1ad3793dc1ba74fce1f6bbca" + }, + { + "codeseparator": null, + "id": "0:173 (bf08bf #3)", + "input": 3, + "txfs": "bf08bf", + "txhash": "0860ad63d2efef87d6efde20d9080387dd28ad71bb9898db5135c19caff0073a" + }, + { + "codeseparator": null, + "id": "0:174 (bf10bf #0)", + "input": 0, + "txfs": "bf10bf", + "txhash": "8ea31d6bb83353a068447bd547b41ee3b1563fd4c83eadfcb707f01f1531b608" + }, + { + "codeseparator": null, + "id": "0:175 (bf10bf #1)", + "input": 1, + "txfs": "bf10bf", + "txhash": "a73e7b8cdaa00ccbc3ad2556a822f9384b5839074f3d2126372ad1065335e883" + }, + { + "codeseparator": null, + "id": "0:176 (bf10bf #2)", + "input": 2, + "txfs": "bf10bf", + "txhash": "cd030648c1326ab4a1f2862fd9af586d3380ad1cb85362b452c1626228a5ff66" + }, + { + "codeseparator": null, + "id": "0:177 (bf10bf #3)", + "input": 3, + "txfs": "bf10bf", + "txhash": "62db9629232ed494eab57cc2c957f61b900d50db4fb7fd9fd0372f0d8c003b74" + }, + { + "codeseparator": null, + "id": "0:178 (bf20bf #0)", + "input": 0, + "txfs": "bf20bf", + "txhash": "5751dc1bc0a8c9bf3ab8bd360836671e963b61ff64c785007d406e1f5fa8450b" + }, + { + "codeseparator": null, + "id": "0:179 (bf20bf #1)", + "input": 1, + "txfs": "bf20bf", + "txhash": "1003eb6423a91c076b72abc6a12ff8b55f5fcc7f764a9937405f6f13cfb9c32c" + }, + { + "codeseparator": null, + "id": "0:180 (bf20bf #2)", + "input": 2, + "txfs": "bf20bf", + "txhash": "48fd8d29a4cbbcfe6e485579c9d2f73cef5ae359602e04051d71390239baef00" + }, + { + "codeseparator": null, + "id": "0:181 (bf20bf #3)", + "input": 3, + "txfs": "bf20bf", + "txhash": "54b67ab8ccfcc7c310019f2f31b5f08ee5dedb6769f8c6db9715144ee19efde3" + }, + { + "codeseparator": null, + "id": "0:182 (bf3fbf #0)", + "input": 0, + "txfs": "bf3fbf", + "txhash": "a052babf78e9fa0019933e85fcd60fb08c86d2364607904976fc68ef334c494c" + }, + { + "codeseparator": null, + "id": "0:183 (bf3fbf #1)", + "input": 1, + "txfs": "bf3fbf", + "txhash": "63bbc9a031a1d08d07dca32d62b30d00266010a8016a52477330b5164c6d1ef0" + }, + { + "codeseparator": null, + "id": "0:184 (bf3fbf #2)", + "input": 2, + "txfs": "bf3fbf", + "txhash": "af79f046431288fc3b9fc066fd6b8a97bc399172138eb13843d760be599b5ebd" + }, + { + "codeseparator": null, + "id": "0:185 (bf3fbf #3)", + "input": 3, + "txfs": "bf3fbf", + "txhash": "5d71f1d36d9fca323beae94c0960ef6399a4db92ca84a670c83c9a6eadc034a3" + }, + { + "codeseparator": null, + "id": "0:186 (bfff3f3f #0)", + "input": 0, + "txfs": "bfff3f3f", + "txhash": "8352120211f422b0291260fbde08f6e3cdf98877ce0da46fa8001b5a00eb9f3b" + }, + { + "codeseparator": null, + "id": "0:187 (bfff3f3f #1)", + "input": 1, + "txfs": "bfff3f3f", + "txhash": "796df7b808c6e0190ebd5a47837b01f5718a5574bfd5518100e10d4ab688b3c7" + }, + { + "codeseparator": null, + "id": "0:188 (bfff3f3f #2)", + "input": 2, + "txfs": "bfff3f3f", + "txhash": "9ae4f9caf70ce4fb4e5e52412b9dadb6f481cd9c3022a343a4806da666909afe" + }, + { + "codeseparator": null, + "id": "0:189 (bfff3f3f #3)", + "input": 3, + "txfs": "bfff3f3f", + "txhash": "bede7c5efb1c013c519f4e2d304c5d766bdb52ef2b649693a4018bc970378be1" + }, + { + "codeseparator": null, + "id": "0:190 (bfff4040 #0)", + "input": 0, + "txfs": "bfff4040", + "txhash": "bd3a0060dce0ffee125c7303cf8deb9f53af1cb6f60b388199ed061dae38e026" + }, + { + "codeseparator": null, + "id": "0:191 (bfff4040 #1)", + "input": 1, + "txfs": "bfff4040", + "txhash": "f9b207b9663e6332b41cd4e690d647f9238336b8cff31716ce62963c3c21a183" + }, + { + "codeseparator": null, + "id": "0:192 (bfff4040 #2)", + "input": 2, + "txfs": "bfff4040", + "txhash": "5486fba88bef133b43a26f68ba953592452d77203a90a8e6a7896341e859726f" + }, + { + "codeseparator": null, + "id": "0:193 (bf008080 #0)", + "input": 0, + "txfs": "bf008080", + "txhash": "5970121aca46194f98e7f7fa955a9500752bdb8cb49a1705f1a946387829d697" + }, + { + "codeseparator": null, + "id": "0:194 (bf008080 #1)", + "input": 1, + "txfs": "bf008080", + "txhash": "6a5b5fca9796169421e0039227db15cc51279c62db500f1f96a360f6fe176f72" + }, + { + "codeseparator": null, + "id": "0:195 (bf008080 #2)", + "input": 2, + "txfs": "bf008080", + "txhash": "c73ea82953932fdffcdca8768eb3f2f42e21c18aefda60ffadb5855ab2b17460" + }, + { + "codeseparator": null, + "id": "0:196 (bf008080 #3)", + "input": 3, + "txfs": "bf008080", + "txhash": "425f2c0449b4006e9f293c540e4c978fc9b1d333076a8d52425bad9282c1b2fb" + }, + { + "codeseparator": null, + "id": "0:197 (bfffbfbf #0)", + "input": 0, + "txfs": "bfffbfbf", + "txhash": "99139e7afdfcf72202c805d873db042f54f42cb6ddaec47f7c87cbadab0dc6cb" + }, + { + "codeseparator": null, + "id": "0:198 (bfffbfbf #1)", + "input": 1, + "txfs": "bfffbfbf", + "txhash": "ad63afd5545942e5bf5b1993e2de70d38d8a84dc311227a55de25180d008a2d1" + }, + { + "codeseparator": null, + "id": "0:199 (bfffbfbf #2)", + "input": 2, + "txfs": "bfffbfbf", + "txhash": "af08d21fec7c93cb30096b3f4affd51b386230857d826a63e33304babd708c9b" + }, + { + "codeseparator": null, + "id": "0:200 (bfffbfbf #3)", + "input": 3, + "txfs": "bfffbfbf", + "txhash": "934c317da06f8d732a51ddedc9cc3c1d6199b1cb09769df2169d2e9bd666fd32" + }, + { + "codeseparator": null, + "id": "0:201 (bfffc0c0 #0)", + "input": 0, + "txfs": "bfffc0c0", + "txhash": "175d763318349d6e42d4e5bd66b9171611ebb70f5a742dee86790760add89030" + }, + { + "codeseparator": null, + "id": "0:202 (bfffc0c0 #1)", + "input": 1, + "txfs": "bfffc0c0", + "txhash": "d6420eeed76078e246d829fc72d6a3ca31a535a92ae6765e2fa36b948355ce7a" + }, + { + "codeseparator": null, + "id": "0:203 (bfffc0c0 #2)", + "input": 2, + "txfs": "bfffc0c0", + "txhash": "218c08631daf9e33d3c3c2e66bd9c62b5d415a0c36ea784306c8d6df34bc4f4a" + }, + { + "codeseparator": null, + "id": "0:204 (bfff403f #0)", + "input": 0, + "txfs": "bfff403f", + "txhash": "e28e7988a2d4c722993a172853cf190d9ad5379c77ce5a6739fc283712d0dd9f" + }, + { + "codeseparator": null, + "id": "0:205 (bfff403f #1)", + "input": 1, + "txfs": "bfff403f", + "txhash": "eae430940a74ec50e5036214fa475b897de9a098383d944ebbd7f57b7a8d6ff8" + }, + { + "codeseparator": null, + "id": "0:206 (bfff403f #2)", + "input": 2, + "txfs": "bfff403f", + "txhash": "f2f7ab612fff345e0258e9233cc8f23c1e9cc354833f50245beb603db77bc7f4" + }, + { + "codeseparator": null, + "id": "0:207 (bfff403f #3)", + "input": 3, + "txfs": "bfff403f", + "txhash": "c520cccc4ad5977ff47647f457fecf7be0a019ae789860131619129d59d25e43" + }, + { + "codeseparator": null, + "id": "0:208 (bfff3f40 #0)", + "input": 0, + "txfs": "bfff3f40", + "txhash": "2f8a3083a15694cfebcf1dcfe73670466c3df14463f5ed956326f49a93e13903" + }, + { + "codeseparator": null, + "id": "0:209 (bfff3f40 #1)", + "input": 1, + "txfs": "bfff3f40", + "txhash": "5c500fc6ab63299fbaa489b9318eaade34ea59a3b89e6b5c1260e8c32e29f2d3" + }, + { + "codeseparator": null, + "id": "0:210 (bfff3f40 #2)", + "input": 2, + "txfs": "bfff3f40", + "txhash": "59ef73e6a3e19a859790a944104b28a3caad931befc54a9a6f6c642d9eedfc4f" + }, + { + "codeseparator": null, + "id": "0:211 (bfff0182 #0)", + "input": 0, + "txfs": "bfff0182", + "txhash": "fcedfac535843c32427207c9db69d51d6f00abc40d70dba7742a91067a2d8189" + }, + { + "codeseparator": null, + "id": "0:212 (bfff0182 #1)", + "input": 1, + "txfs": "bfff0182", + "txhash": "e5eba524dded1b075815c1f93a916fc060c9b066884eb61d02abd699b8aca73b" + }, + { + "codeseparator": null, + "id": "0:213 (bfff0182 #2)", + "input": 2, + "txfs": "bfff0182", + "txhash": "aac43bc494d5f488b5272d818170e011d7a5e0c6f2c3e593b2bf3b0b51787a11" + }, + { + "codeseparator": null, + "id": "0:214 (bfff0182 #3)", + "input": 3, + "txfs": "bfff0182", + "txhash": "1c6306da9a8864b4be2323e4a9e12c00eb27c3a6c40e8a22506fd433e5e9f8fb" + }, + { + "codeseparator": null, + "id": "0:215 (bfffc002 #0)", + "input": 0, + "txfs": "bfffc002", + "txhash": "9d0fcba07903ab0b5d514b0d4504dd3644e1a04a1fa0926310b673bcb0bac625" + }, + { + "codeseparator": null, + "id": "0:216 (bfffc002 #1)", + "input": 1, + "txfs": "bfffc002", + "txhash": "c325c9a8f2b875f59b7c15a6441f1b3910682a2783725dafd74ce6ef1142bbc0" + }, + { + "codeseparator": null, + "id": "0:217 (bfffc002 #2)", + "input": 2, + "txfs": "bfffc002", + "txhash": "74ae80b6f986d09462494f86f0892b41db673ecc4f18bd97ab93736f4f1ea197" + }, + { + "codeseparator": null, + "id": "0:218 (bfff4101420002 #0)", + "input": 0, + "txfs": "bfff4101420002", + "txhash": "c272e0e2eabbf7d7fcc02d4bb3c91293051a1545be0c30312b66117471f6fb35" + }, + { + "codeseparator": null, + "id": "0:219 (bfff4101420002 #1)", + "input": 1, + "txfs": "bfff4101420002", + "txhash": "f37687e23ff5fbc3338b7918bac938c82cf9506b37f6fa2e2d83aaf93524b5df" + }, + { + "codeseparator": null, + "id": "0:220 (bfff4101420002 #2)", + "input": 2, + "txfs": "bfff4101420002", + "txhash": "fbdc9f142020acb625088bb67ed590af11a05a7607586b68644171dc66219b29" + }, + { + "codeseparator": null, + "id": "0:221 (bfff4101420002 #3)", + "input": 3, + "txfs": "bfff4101420002", + "txhash": "e58121a9d4e5ae4f522c7eb39df94dff04dae5573ffcd0b810117589ec7febcc" + }, + { + "codeseparator": null, + "id": "0:222 (bfffc101c20002 #0)", + "input": 0, + "txfs": "bfffc101c20002", + "txhash": "73b3fe9fa2f90f063966aadca0a36a9093725ad040af6b070135d1503b620d48" + }, + { + "codeseparator": null, + "id": "0:223 (bfffc101c20002 #1)", + "input": 1, + "txfs": "bfffc101c20002", + "txhash": "46aa5607904cfadd3483b7a61706f8b0d7089d19b4d6fed02f071bedc7b6dbae" + }, + { + "codeseparator": null, + "id": "0:224 (bfffc101c20002 #2)", + "input": 2, + "txfs": "bfffc101c20002", + "txhash": "f588b0e1a97e51b0cca91258159262e5a08758a165d2d96d3b1f46f13e653b5f" + }, + { + "codeseparator": null, + "id": "0:225 (bfffc101c20002 #3)", + "input": 3, + "txfs": "bfffc101c20002", + "txhash": "fffdc8629c2ac13efcf66d1cb79c5b8e6bfcdefb4e541740682fee048d7de7a1" + }, + { + "codeseparator": null, + "id": "0:226 (bfff617f627f00 #1)", + "input": 1, + "txfs": "bfff617f627f00", + "txhash": "3abc580aa956e40cb60aef3eb07135e910eff2f4c00211876a0863e8fa79d89c" + }, + { + "codeseparator": null, + "id": "0:227 (bfff617f627f00 #2)", + "input": 2, + "txfs": "bfff617f627f00", + "txhash": "d9503d415d9a94fa88fe4139a3afa6f3b77f28b693fba9df31945ef6f37548b5" + }, + { + "codeseparator": null, + "id": "0:228 (bfffe17fe27f00 #1)", + "input": 1, + "txfs": "bfffe17fe27f00", + "txhash": "20f12c5960847e0a7d1ee98043787a3e937cb830bfe0aedf233b5456964535ec" + }, + { + "codeseparator": null, + "id": "0:229 (bfffe17fe27f00 #2)", + "input": 2, + "txfs": "bfffe17fe27f00", + "txhash": "fb1a1e2760d3b93f33e92be7080d8ba676dcae379e0e541a3fc59269f5ed9d48" + }, + { + "codeseparator": null, + "id": "0:230 ( #0)", + "input": 0, + "txfs": "", + "txhash": "f4afe580e3bcf635c46c12f224f259f9354a4eff06e81550e35aa553820ba88f" + }, + { + "codeseparator": null, + "id": "0:231 ( #1)", + "input": 1, + "txfs": "", + "txhash": "8f1becde41b585ab91b8039c9ab95091f18b4f52d5aa906ae5c22b62c623f07a" + }, + { + "codeseparator": null, + "id": "0:232 ( #2)", + "input": 2, + "txfs": "", + "txhash": "9f1a08a5dc364939ac23ee245bf4c258d2cfe88a6c8305aa4b834ce57faf671c" + }, + { + "codeseparator": null, + "id": "0:233 ( #3)", + "input": 3, + "txfs": "", + "txhash": "cde83ca2e79ac4277477995f48b2e63ae41b35e1ebf07b39bfe9ce0f994dd79f" + }, + { + "codeseparator": null, + "id": "0:234 (00 #0)", + "input": 0, + "txfs": "00", + "txhash": "99139e7afdfcf72202c805d873db042f54f42cb6ddaec47f7c87cbadab0dc6cb" + }, + { + "codeseparator": null, + "id": "0:235 (00 #1)", + "input": 1, + "txfs": "00", + "txhash": "ad63afd5545942e5bf5b1993e2de70d38d8a84dc311227a55de25180d008a2d1" + }, + { + "codeseparator": null, + "id": "0:236 (00 #2)", + "input": 2, + "txfs": "00", + "txhash": "af08d21fec7c93cb30096b3f4affd51b386230857d826a63e33304babd708c9b" + }, + { + "codeseparator": null, + "id": "0:237 (00 #3)", + "input": 3, + "txfs": "00", + "txhash": "934c317da06f8d732a51ddedc9cc3c1d6199b1cb09769df2169d2e9bd666fd32" + } + ] + } +] \ No newline at end of file