3

How can I decode a raw transaction using Go / go-ethereum ? There is no method/function to read the raw bytes or the hex into a transaction https://godoc.org/github.com/ethereum/go-ethereum/core/types . Basically I just want to extract the destination address and the amount sent.

4

4 Answers 4

4

Using the official go-ethereum package:

import (
    "encoding/hex"

    "github.com/ethereum/go-ethereum/common"
    "github.com/ethereum/go-ethereum/core/types"
    "github.com/ethereum/go-ethereum/rlp"
)

func GetToAddressFromRawTransaction(rawTxHex string) (*common.Address, error) {
    rawTxData, err := hex.DecodeString(rawTxHex[2:]) // Remove hex prefix "0x..."
    if err != nil {
        return nil, err
    }

    var tx types.Transaction
    err = rlp.DecodeBytes(rawTxData, &tx)
    if err != nil {
        return nil, err
    }

    return tx.To(), nil
}

Look at the methods of the Transaction type to access data in the tx object.

Here's a working code on github

2
  • may I ask what are you doing in that loop to decode the public key ??? What are the sig1 and sig2 and why do you need a public key at all?
    – Nulik
    Jun 21, 2018 at 2:32
  • @Nulik For normal using of blockchain you don't need a public key. But if you want to research or to know deeper about EC cryptography you might be eager to find a public key. In my code sig1 and sig2 is a signature of the message. It consists of R+S+V (learn more about elliptic curves). R and S are known. V can be 00 or 01, so we just check both options.
    – Tarik
    Jun 22, 2018 at 10:47
1

With introduction of EIP-1559, rlp.DecodeBytes(..) no longer works and you'd have to use tx.UnmarshalBinary(..) instead. Here's an example:

package main

import (
    "github.com/davecgh/go-spew/spew"
)

func deraw() {

    // eip-1559 tx: 0xc2163f50770bd4bfd3c13848b405a56a451ae2a39cfa5a236ea2738ce44aa9df
    rawTx := "02f8740181bf8459682f00851191460ee38252089497e542ec6b81dea28f212775ce8ac436ab77a7df880de0b6b3a764000080c080a02bc11202cee115fe22558ce2edb25c621266ce75f75e9b10da9a2ae72460ad4ea07d573eef31fdebf0f5f93eb7721924a082907419eb97a8dda0dd20a4a5b954a1"

    // legacy tx
    //rawTx := "f86d8202b28477359400825208944592d8f8d7b001e72cb26a73e4fa1806a51ac79d880de0b6b3a7640000802ca05924bde7ef10aa88db9c66dd4f5fb16b46dff2319b9968be983118b57bb50562a001b24b31010004f13d9a26b320845257a6cfc2bf819a3d55e3fc86263c5f0772"

    tx := &types.Transaction{}
    rawTxBytes, err := hex.DecodeString(rawTx)
    if err != nil {
        fmt.Println("err:", err)
        return 1
    }

    err = tx.UnmarshalBinary(rawTxBytes)
    if err != nil {
        fmt.Println("err:", err)
        return 1
    }

    spew.Dump(tx)
}

Alternatively, you can extract what you want using rlpdump.

1
  • This should be the top answer! huge thx, been bugging me for days
    – gabkov
    Jan 25 at 15:56
0

Here is a package I found out about from this answer:

https://github.com/ConsenSys/abi-decoder

See the code block titled Decode Tx data. I think this should do what you want.

2
  • Can you understand the difference between javascript and Go ?
    – Books
    Jan 24, 2018 at 20:17
  • Ok. Ok. I should read questions more carefully. go-ethereum also has a Javascript API to communicate with the node using IPC or RPC. That is what I have always used because I programmed in Javascript. Perhaps, when you said Go / go-ethereum, you meant an application in Go (i.e. not Javascript) interacting with the go-ethereum client? Jan 24, 2018 at 20:32
0

Here's a full example of how to read transaction values (ie, from address, eth value, etc..) in Go.

package main

import (
    "context"
    "fmt"
    "log"
    "math/big"

    "github.com/ethereum/go-ethereum/core/types"
    "github.com/ethereum/go-ethereum/ethclient"
)

func main() {
    client, err := ethclient.Dial("https://mainnet.infura.io")
    if err != nil {
        log.Fatal(err)
    }

    blockNumber := big.NewInt(5671744)
    block, err := client.BlockByNumber(context.Background(), blockNumber)
    if err != nil {
        log.Fatal(err)
    }

    for _, tx := range block.Transactions() {
        fmt.Println(tx.Hash().Hex())        // 0x5d49fcaa394c97ec8a9c3e7bd9e8388d420fb050a52083ca52ff24b3b65bc9c2
        fmt.Println(tx.Value().String())    // 10000000000000000
        fmt.Println(tx.Gas())               // 105000
        fmt.Println(tx.GasPrice().Uint64()) // 102000000000
        fmt.Println(tx.Nonce())             // 110644
        fmt.Println(tx.Data())              // []
        fmt.Println(tx.To().Hex())          // 0x55fE59D8Ad77035154dDd0AD0388D09Dd4047A8e

        if msg, err := tx.AsMessage(types.HomesteadSigner{}); err != nil {
            fmt.Println(msg.From().Hex()) // 0x0fD081e3Bb178dc45c0cb23202069ddA57064258
        }

        receipt, err := client.TransactionReceipt(context.Background(), tx.Hash())
        if err != nil {
            log.Fatal(err)
        }

        fmt.Println(receipt.Status) // 1
    }
}

If you have the raw tx hex, here's how you can decode it into a tx type:

package main

import (
    "encoding/hex"
    "log"

    "github.com/c3systems/vendor.bak/github.com/davecgh/go-spew/spew"
    "github.com/ethereum/go-ethereum/core/types"
    "github.com/ethereum/go-ethereum/ethclient"
    "github.com/ethereum/go-ethereum/rlp"
)

func main() {
    client, err := ethclient.Dial("https://rinkeby.infura.io")
    if err != nil {
        log.Fatal(err)
    }

    rawTx := "f86d8202b28477359400825208944592d8f8d7b001e72cb26a73e4fa1806a51ac79d880de0b6b3a7640000802ca05924bde7ef10aa88db9c66dd4f5fb16b46dff2319b9968be983118b57bb50562a001b24b31010004f13d9a26b320845257a6cfc2bf819a3d55e3fc86263c5f0772"

    var tx *types.Transaction

    rawTxBytes, err := hex.DecodeString(rawTx)
    rlp.DecodeBytes(rawTxBytes, &tx)

    spew.Dump(tx)
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.