Skip to content

Instantly share code, notes, and snippets.

@fjl
Last active June 11, 2019 12:50
Show Gist options
  • Save fjl/69454fe6b56d04b3c4932d8673dedc63 to your computer and use it in GitHub Desktop.
Save fjl/69454fe6b56d04b3c4932d8673dedc63 to your computer and use it in GitHub Desktop.
package main
import (
"context"
"encoding/json"
"fmt"
"math/big"
"math/rand"
"os"
"time"
"github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/ethereum/go-ethereum/rpc"
)
// Ganache: ./cli.js -i 1337 --account '0xc9fad8bf34b84f5daa5f5d84cdf02ae9b3541abd5f570e834c57561eb161c743,100000000000000000000000'
var (
server = "http://127.0.0.1:8545"
privkey, _ = crypto.HexToECDSA("c9fad8bf34b84f5daa5f5d84cdf02ae9b3541abd5f570e834c57561eb161c743")
chainID = big.NewInt(1337)
)
func main() {
rawclient, err := rpc.Dial(server)
if err != nil {
panic(err)
}
defer rawclient.Close()
ec := ethclient.NewClient(rawclient)
// Create and send the test transaction:
var (
signer = types.NewEIP155Signer(chainID)
tx = testTransaction(ec, signer)
ctx, cancel = context.WithTimeout(context.Background(), 10*time.Second)
enc = json.NewEncoder(os.Stdout)
)
defer cancel()
enc.Encode(tx)
if err := ec.SendTransaction(ctx, tx); err != nil {
panic("can't send transaction: " + err.Error())
}
// Wait for inclusion.
for {
receipt, err := ec.TransactionReceipt(ctx, tx.Hash())
if err == ethereum.NotFound {
time.Sleep(time.Second)
} else if err != nil {
panic("can't get receipt: " + err.Error())
} else {
fmt.Print("test transaction included: ")
enc.Encode(receipt)
break
}
}
// Try to load the transaction back from the server.
var (
rawServerTx json.RawMessage
serverTx types.Transaction
)
if err := rawclient.CallContext(ctx, &rawServerTx, "eth_getTransactionByHash", tx.Hash()); err != nil {
panic("can't get transaction from server: " + err.Error())
}
fmt.Println("server returned:", string(rawServerTx))
fmt.Println("unmarshal error:", json.Unmarshal(rawServerTx, &serverTx))
}
func testTransaction(ec *ethclient.Client, signer types.Signer) *types.Transaction {
for i := 0; ; i++ {
var (
ctx, cancel = context.WithTimeout(context.Background(), 5*time.Second)
randomData = make([]byte, rand.Intn(1000))
srcAddr = crypto.PubkeyToAddress(privkey.PublicKey)
dstAddr = common.HexToAddress("0xeA900b586a1036fa7505FB542AdC687757e18fAf")
value = big.NewInt(1)
msg = ethereum.CallMsg{From: srcAddr, To: &dstAddr, Value: value, Data: randomData}
)
fmt.Println("mining test tx round", i)
rand.Read(randomData)
// Determine gas and nonce.
gasPrice, err := ec.SuggestGasPrice(ctx)
if err != nil {
panic("can't get gas price: " + err.Error())
}
gas, err := ec.EstimateGas(ctx, msg)
if err != nil {
panic("can't estimate tx gas: " + err.Error())
}
nonce, err := ec.PendingNonceAt(ctx, srcAddr)
if err != nil {
panic("can't get nonce: " + err.Error())
}
// Sign the transaction.
tx := types.NewTransaction(nonce, *msg.To, msg.Value, gas, gasPrice, randomData)
signedTx, err := types.SignTx(tx, signer, privkey)
if err != nil {
panic("can't sign transaction: " + err.Error())
}
// Ensure tx will have leading zero in R or S when encoded as JSON.
_, r, s := signedTx.RawSignatureValues()
if r.BitLen() > 248 && r.BitLen() < 252 || s.BitLen() > 248 && s.BitLen() < 252 {
return signedTx
}
cancel()
}
return nil
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment