Go-Ethereum

Go 中的原始交易數據

  • June 7, 2018

我想在golang沒有任何go綁定的情況下生成原始事務,我想知道是否有庫可以使用動態編碼我的參數參數go

https://github.com/ethereum/wiki/wiki/Ethereum-Contract-ABI

使用此資源,為每種可用數據類型手動動態編碼每個參數似乎需要大量工作。

有沒有辦法做到這一點?

同樣,我不是在尋找Ethereum Go 綁定,因為我需要返回原始的未簽名交易數據。

go-ethereum 包為soliditycommon.LeftPadBytes的左填充值提供了一個函式。您可以使用它來填充 32 個字節,這是 EVM 使用的字長。

這是一個完整範例,說明如何手動建構用於傳輸 ERC-20 代幣的交易數據,這應該會給您一個好主意(來自Ethereum Development with Go 書)。

package main

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

   "github.com/ethereum/go-ethereum/common"
   "github.com/ethereum/go-ethereum/common/hexutil"
   "github.com/ethereum/go-ethereum/core/types"
   "github.com/ethereum/go-ethereum/crypto"
   "github.com/ethereum/go-ethereum/crypto/sha3"
   "github.com/ethereum/go-ethereum/ethclient"
)

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

   privateKey, err := crypto.HexToECDSA("fad9c8855b740a0b7ed4c221dbad0f33a83a49cad6b3fe8d5817ac83d38b6a19")
   if err != nil {
       log.Fatal(err)
   }

   publicKey := privateKey.Public()
   publicKeyECDSA, ok := publicKey.(*ecdsa.PublicKey)
   if !ok {
       log.Fatal("error casting public key to ECDSA")
   }

   fromAddress := crypto.PubkeyToAddress(*publicKeyECDSA)
   nonce, err := client.PendingNonceAt(context.Background(), fromAddress)
   if err != nil {
       log.Fatal(err)
   }

   value := big.NewInt(0)      // in wei (0 eth)
   gasLimit := uint64(2000000) // in units
   gasPrice, err := client.SuggestGasPrice(context.Background())
   if err != nil {
       log.Fatal(err)
   }

   toAddress := common.HexToAddress("0x4592d8f8d7b001e72cb26a73e4fa1806a51ac79d")
   tokenAddress := common.HexToAddress("0x28b149020d2152179873ec60bed6bf7cd705775d")

   transferFnSignature := []byte("transfer(address,uint256)")
   hash := sha3.NewKeccak256()
   hash.Write(transferFnSignature)
   methodID := hash.Sum(nil)[:4]
   fmt.Println(hexutil.Encode(methodID)) // 0xa9059cbb

   paddedAddress := common.LeftPadBytes(toAddress.Bytes(), 32)
   fmt.Println(hexutil.Encode(paddedAddress)) // 0x0000000000000000000000004592d8f8d7b001e72cb26a73e4fa1806a51ac79d

   amount := new(big.Int)
   amount.SetString("1000000000000000000000", 10) // 1000 tokens
   paddedAmount := common.LeftPadBytes(amount.Bytes(), 32)
   fmt.Println(hexutil.Encode(paddedAmount)) // 0x00000000000000000000000000000000000000000000003635c9adc5dea00000

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

   tx := types.NewTransaction(nonce, tokenAddress, value, gasLimit, gasPrice, data)
   signedTx, err := types.SignTx(tx, types.HomesteadSigner{}, 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()) // tx sent: 0xa56316b637a94c4cc0331c73ef26389d6c097506d581073f927275e7a6ece0bc
}

一個開始的地方是NewTransaction()transaction.go。這是types包裝的一部分。

// NewTransaction creates a new transaction with the given properties.
func NewTransaction(nonce int64, to *Address, amount, gasLimit, gasPrice *BigInt, data []byte) *Transaction {
   return &Transaction{types.NewTransaction(uint64(nonce), to.address, amount.bigint, gasLimit.bigint, gasPrice.bigint, data)}
}

程式碼中有無數的地方有如何測試函式的例子,不管有沒有執行簽名的步驟。

引用自:https://ethereum.stackexchange.com/questions/10486