Go-Ethereum
Go 中的原始交易數據
我想在
golang
沒有任何go
綁定的情況下生成原始事務,我想知道是否有庫可以使用動態編碼我的參數參數go
?https://github.com/ethereum/wiki/wiki/Ethereum-Contract-ABI
使用此資源,為每種可用數據類型手動動態編碼每個參數似乎需要大量工作。
有沒有辦法做到這一點?
同樣,我不是在尋找Ethereum Go 綁定,因為我需要返回原始的未簽名交易數據。
go-ethereum 包為solidity
common.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)} }
程式碼中有無數的地方有如何測試函式的例子,不管有沒有執行簽名的步驟。