-
-
Save fjl/69454fe6b56d04b3c4932d8673dedc63 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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