celo-org / celo-blockchain

Official repository for the golang Celo Blockchain
https://celo.org
GNU Lesser General Public License v3.0
548 stars 195 forks source link

golang signing tx's: rlp error: input string too short for common.Address #835

Closed daithi-coombes closed 4 years ago

daithi-coombes commented 4 years ago

Expected Behavior

Singed transaction would be processed successfully. Log in geth --verbosity 3 would show transaction.

Current Behavior

Receiving the error:

rlp: input string too short for common.Address, decoding into (types.Transaction)(types.txdata).Recipient

First I tried using the go-ethereum bindings created running truffle compile against the mono-repo/packages/protocol repo. I then used abigen to create the go bindings. Calling anything on a contract returned the above error. (more info on implementation used commented here https://github.com/ethereum/go-ethereum/issues/16290#issuecomment-579622015)

Next I tried singing the transactions in vanilla go without the bindings created from abigen.

func Transfer(to common.Address, from common.Address, amount *big.Int, client *ethclient.Client) {

    // TODO: DELETE DELETE DELETE DELETE
    deleteThis_PASSWORD := "****"
    keystoreKey, e := keystore.DecryptKey([]byte(`{}`), deleteThis_PASSWORD)
    if e != nil {
        log.Fatal(e)
    }

    // get data field
    value := big.NewInt(0)
    tokenAddress := common.HexToAddress("0x5c7197e1147ebf98658a2a8bc3d32bebf1692829")
    transferFnSig := []byte("transfer(address,uint256)")
    //method id
    hash := sha3.NewLegacyKeccak256()
    hash.Write(transferFnSig)
    methodID := hash.Sum(nil)[:4]
    fmt.Printf("hexutil.Encode(methodID): %v\n", hexutil.Encode(methodID))
    paddedAddress := common.LeftPadBytes(to.Bytes(), 32)
    paddedAmount := common.LeftPadBytes(amount.Bytes(), 32)
    fmt.Printf("hexutil.Encode(paddedAmount): %v\n", hexutil.Encode(paddedAmount))

    // build payload
    var data []byte
    data = append(data, methodID...)
    data = append(data, paddedAddress...)
    data = append(data, paddedAmount...)

    // gas limit & Price
    gasLimit, err := client.EstimateGas(context.Background(), ethereum.CallMsg{
        To:   &tokenAddress,
        Data: data,
    })
    if err != nil {
        log.Fatal(err)
    }
    fmt.Printf("gasLimit: %v\n", gasLimit)
    gasPrice, err := client.SuggestGasPrice(context.Background())
    if err != nil {
        log.Fatal(err)
    }

    // get nonce
    nonce, err := client.PendingNonceAt(context.Background(), from)
    if err != nil {
        log.Fatal(err)
    }

    // create tx
    tx := types.NewTransaction(nonce, tokenAddress, value, gasLimit, gasPrice, data)

    chainID, err := client.NetworkID(context.Background())
    if err != nil {
        log.Fatal(err)
    }
    signedTx, err := types.SignTx(tx, types.NewEIP155Signer(chainID), keystoreKey.PrivateKey)
    if err != nil {
        log.Fatal(err)
    }

    err = client.SendTransaction(context.Background(), signedTx)
    if err != nil {
        log.Fatal(err)
    }
    fmt.Printf("tx sent: %s", signedTx.Hash().Hex())
}

Steps to Reproduce Behavior

Call the above function

Logs

No logs on node

System information

Run geth version

$ docker exec -it celo-accounts geth version
WARN [01-29|09:19:53.766] Sanitizing cache to Go's GC limits       provided=1024 updated=663
lsb_release -a: exec: "lsb_release": executable file not found in $PATH
Geth Version: 1.8.23-stable

Go Version: go1.11.13
GOPATH=
GOROOT=/usr/local/go

Architecture: amd64
Operating System: linux
uname -sr: Linux 4.19.76-linuxkit
daithi-coombes commented 4 years ago

Am wondering if it might be related to this issue: https://github.com/celo-org/celo-blockchain/pull/298

daithi-coombes commented 4 years ago

found it in @celo/contractkit: https://www.npmjs.com/package/@celo/contractkit#sending-custom-transactions

Celo transaction object is not the same as Ethereum's. There are three new fields present:

    feeCurrency (address of the ERC20 contract to use to pay for gas and the gateway fee)
    gatewayFeeRecipient (coinbase address of the full serving the light client's trasactions)
    gatewayFee (value paid to the gateway fee recipient, denominated in the fee currency)

This means that using web3.eth.sendTransaction or myContract.methods.transfer().send() should be avoided.
daithi-coombes commented 4 years ago

golang solution is to use celo's implementation in this package here: https://github.com/celo-org/celo-blockchain/blob/master/accounts/abi/bind/base.go

closing.