SCRIPTS

Useful programs & scripts

BITCOIN TRANSACTION DECODER

Bitcoin has revolutionized society. It offers an almost miraculous alterantive to the FIAT hellhole we've been led into that the powers that be have tried to dismiss and demonize to no avail. To many, this alone translates into a potential scenario where the economy isn't regulated by a handful of nameless oligarchs but by the collective computational power of cyberspace. The secret to bitcoin's power? The blockchain.


I wrote a blog post covering some technical details as well as the motivations behind this script, make sure to check it out for more background info. As for the script itself, it decodes the output (receiving) addresses of a given bitcoin transaction in the original order, this in an attempt to reveal a hidden message. The transaction data is taken from the Blockchain.com transaction explorer, removing the need for a local copy of the bitcoin blockchain, all it needs is a valid TX hash.


import sys
import urllib3
import base58


def findSubStr(ogStr, subStr):
    hits = [i for i in range(len(ogStr)) if ogStr.startswith(subStr, i)]
    return hits


def decodeTX(txNum):
    http = urllib3.PoolManager()
    txData = http.request(
        "GET", "https://blockchain.info/tx/" + txNum + "?show_adv=true")

    # Decode the raw bytes received
    dataStr = txData.data.decode('utf-8')

    atOutput = False
    if (dataStr.find("output scripts")):
        dataStr = dataStr[dataStr.find("output scripts"):]
        # Remove the trailing CSS style code
        if (dataStr.find("<style")):
            dataStr = dataStr[: dataStr.find("<style ")]

        # Trim the unnecessary content
        dataStr = dataStr[dataStr.find('"outputs":'):dataStr.find('"config":')]
        addrSubStr = findSubStr(dataStr, "address")
        if (len(addrSubStr) < 1):
            print("Invalid transaction hash!")
            exit()
        print("Total output addresses found: " + str(len(addrSubStr)))
        # print(addrSubStr)
        counter = 0
        totalData = b""
        for i in addrSubStr:
            counter += 1
            # Isolate the address
            addr = dataStr[i+10:i+46]
            addr = addr[:addr.find('"')]
            # Check for invalid / empty adresses
            if (':' in addr or ',' in addr):
                continue
            addrDecoded = base58.b58decode_check(addr)
            totalData += addrDecoded
            print("["+str(counter)+"]" + addr + "d: " + str(addrDecoded))

        print("Total bytes extracted: " + str(len(totalData)))
        print("Saving data to "+txNum)

        # Save the decoded data into a file with the transaction hash as name
        # Not all the decoded bytes have an ASCII equivalent or even proper alignement / syntax
        # so decoding it with python's .decode('ascii') usually fails
        # Running cat on the file does a much better job printing the data
        saveFileBinary = open(txNum, "wb")
        saveFileBinary.write(totalData)
        saveFileBinary.close()


if __name__ == "__main__":
    print("TX Hash: " + str(sys.argv[1]))
    decodeTX(str(sys.argv[1]))

                

As an example, we decode a well-known hidden message in transaction 930a2114cdaa86e1fac46d15c74e81c09eee1d4150ff9d48e76cb0697d8e1d72. The extracted, decoded output is also stored in a file named after it's transaction hash.


Left: Encoded output addresses | Right: Decoded ASCII


It's worth pointing out that this is one of a handful of ways a user can sneak in data into the blockchain!