| 81 | |
| 82 | |
| 83 | ScriptOutputDataType extractScriptData(const blocksci::CScriptView &scriptPubKey, bool p2shActivated, bool witnessActivated) { |
| 84 | using blocksci::AddressType; |
| 85 | using blocksci::CScript; |
| 86 | using blocksci::CScriptView; |
| 87 | using blocksci::uint160; |
| 88 | using blocksci::uint256; |
| 89 | |
| 90 | // Shortcut for pay-to-script-hash, which are more constrained than the other types: |
| 91 | // it is always OP_HASH160 20 [20 byte hash] OP_EQUAL |
| 92 | if (p2shActivated && scriptPubKey.IsPayToScriptHash()) { |
| 93 | blocksci::uint160 hash; |
| 94 | memcpy(&hash, &(*(scriptPubKey.begin()+2)), 20); |
| 95 | return ScriptOutputData<AddressType::Enum::SCRIPTHASH>{{hash}}; |
| 96 | } |
| 97 | |
| 98 | uint8_t witnessversion; |
| 99 | ranges::subrange<const unsigned char *> witnessprogram; |
| 100 | if (witnessActivated && scriptPubKey.IsWitnessProgram(witnessversion, witnessprogram)) { |
| 101 | if (witnessversion == 0) { |
| 102 | if (witnessprogram.size() == 20) { |
| 103 | return ScriptOutputData<AddressType::Enum::WITNESS_PUBKEYHASH>(uint160{witnessprogram.begin(), witnessprogram.end()}); |
| 104 | } else if (witnessprogram.size() == 32) { |
| 105 | return ScriptOutputData<AddressType::Enum::WITNESS_SCRIPTHASH>(uint256{witnessprogram.begin(), witnessprogram.end()}); |
| 106 | } else { |
| 107 | // Witness v0 with other script length is treated as nonstandard |
| 108 | return ScriptOutputData<AddressType::Enum::NONSTANDARD>{scriptPubKey}; |
| 109 | } |
| 110 | } else { |
| 111 | return ScriptOutputData<AddressType::Enum::WITNESS_UNKNOWN>(witnessversion, witnessprogram); |
| 112 | } |
| 113 | } |
| 114 | |
| 115 | // Provably prunable, data-carrying output |
| 116 | // |
| 117 | // So long as script passes the IsUnspendable() test and all but the first |
| 118 | // byte passes the IsPushOnly() test we don't care what exactly is in the |
| 119 | // script. |
| 120 | |
| 121 | if (scriptPubKey.size() >= 1 && scriptPubKey[0] == OP_RETURN && scriptPubKey.IsPushOnly(scriptPubKey.begin()+1)) { |
| 122 | return ScriptOutputData<AddressType::Enum::NULL_DATA>{scriptPubKey}; |
| 123 | } |
| 124 | |
| 125 | ranges::subrange<const unsigned char *> data; |
| 126 | if (MatchPayToPubkey(scriptPubKey, data)) { |
| 127 | return ScriptOutputData<AddressType::Enum::PUBKEY>{data}; |
| 128 | } |
| 129 | |
| 130 | if (MatchPayToPubkeyHash(scriptPubKey, data)) { |
| 131 | auto address = uint160{data.begin(), data.end()}; |
| 132 | return ScriptOutputData<AddressType::Enum::PUBKEYHASH>{address}; |
| 133 | } |
| 134 | |
| 135 | ScriptOutputData<blocksci::AddressType::Enum::MULTISIG> multisigOutput; |
| 136 | if (MatchMultisig(scriptPubKey, multisigOutput)) { |
| 137 | return multisigOutput; |
| 138 | } |
| 139 | |
| 140 | return ScriptOutputData<AddressType::Enum::NONSTANDARD>{scriptPubKey}; |
no test coverage detected