Skip to content

Instantly share code, notes, and snippets.

@robbinhan
Created April 3, 2018 06:45
Show Gist options
  • Save robbinhan/9655c5ca7619e9924bc973201c4cfc71 to your computer and use it in GitHub Desktop.
Save robbinhan/9655c5ca7619e9924bc973201c4cfc71 to your computer and use it in GitHub Desktop.
package app
import (
"bytes"
"encoding/json"
"ethereum-benchmark/config"
"fmt"
"io/ioutil"
"log"
"net/http"
"time"
)
type EthApiJson struct {
Jsonrpc string `json:"jsonrpc"`
Method string `json:"method"`
Params interface{} `json:"params"`
Id int64 `json:"id"`
}
type EthApiJsonError struct {
Code int `json:"code"`
Message string `json:"message"`
}
type EthApiJsonRes struct {
Error EthApiJsonError `json:"error"`
Result string `json:"result"`
}
type AddrConf struct {
UrlPort string
Password string
}
type App struct {
M map[string]*AddrConf
Conf *config.GlobalConfigurations
Trans *config.TransferConfiguration
}
func (a *App) Run() {
var i int
for {
for _, t := range a.Trans.Transactions {
// 并发量
if i < a.Trans.Concurrency {
go a.translate(t)
i++
continue
}
// 时间间隔
time.Sleep(time.Duration(a.Trans.Interval) * time.Millisecond)
i = 0
}
}
return
}
func (a *App) unlock(addr string) {
conf, found := a.M[addr]
if !found {
return
}
addrData := []string{addr, conf.Password}
apiJson := EthApiJson{
Jsonrpc: "2.0",
Method: "personal_unlockAccount",
Params: addrData,
Id: 1,
}
data, err := json.Marshal(apiJson)
if err != nil {
//log.Println(err)
return
}
ethCall(conf.UrlPort, data)
return
}
func (a *App) translate(transaction config.Trans) {
conf, found := a.M[transaction.AccountFrom]
if !found {
return
}
transData := []struct {
From string `json:"from"`
To string `json:"to"`
Value string `json:"value"`
}{
{
From: transaction.AccountFrom,
To: transaction.AccountTo,
Value: fmt.Sprintf("0x%x", transaction.Amount),
},
}
data, err := json.Marshal(transData)
if err != nil {
//log.Println(err)
return
}
apiJson := EthApiJson{
Jsonrpc: "2.0",
Method: "eth_sendTransaction",
Params: transData,
Id: 1,
}
data, err = json.Marshal(apiJson)
if err != nil {
//log.Println(err)
return
}
result := ethCall(conf.UrlPort, data)
if result == nil {
return
}
if result.Error.Code == 0 {
log.Println("-------result------", result.Result)
} else {
log.Println("-------error------", result.Error.Code, result.Error.Message)
switch result.Error.Message {
case ErrorAccountUnlockMessage:
a.unlock(transaction.AccountFrom)
default:
}
}
return
}
func ethCall(urlPort string, data []byte) *EthApiJsonRes {
client := &http.Client{}
request, err := http.NewRequest("post", urlPort, bytes.NewBuffer(data))
if err != nil {
//log.Println(err)
return nil
}
request.Header.Set("Content-type", "application/json")
// log.Println("------ethCall---start----", time.Now().Format("2006-01-02 15:04:05.000"), urlPort, string(data))
response, err := client.Do(request)
if err != nil {
//log.Println(err)
return nil
}
defer func() {
//log.Println("------ethCall---end----", time.Now().Format("2006-01-02 15:04:05.000"))
response.Body.Close()
}()
if response.StatusCode == 200 {
body, err := ioutil.ReadAll(response.Body)
if err != nil {
//log.Println(err)
return nil
}
var res EthApiJsonRes
if err := json.Unmarshal(body, &res); err != nil {
//log.Println(err)
return nil
}
return &res
}
return nil
}
package config
import (
"encoding/json"
"io/ioutil"
)
type Addr struct {
Address string `json:"address"`
Password string `json:"password"`
}
type GlobalConfiguration struct {
NodeIp string `json:"node_ip"`
NodePort string `json:"node_port"`
AddrStore []Addr `json:"addr_store"`
}
type GlobalConfigurations []GlobalConfiguration
func (gc *GlobalConfigurations) Parse(confPath string) error {
data, err := ioutil.ReadFile(confPath)
if err != nil {
return err
}
return json.Unmarshal(data, gc)
}
type Trans struct {
AccountFrom string `json:"account_from"`
AccountTo string `json:"account_to"`
Amount int `json:"amount"`
}
type TransferConfiguration struct {
Interval int `json:"interval"`
Concurrency int `json:"concurrency"`
Transactions []Trans `json:"transactions"`
}
func (tcs *TransferConfiguration) Parse(confPath string) error {
data, err := ioutil.ReadFile(confPath)
if err != nil {
return err
}
return json.Unmarshal(data, tcs)
}
package app
const ErrorAccountUnlockCode = -32000
const ErrorAccountUnlockMessage = "authentication needed: password or unlock"
package main
import (
"ethereum-benchmark/app"
"ethereum-benchmark/config"
"fmt"
)
const PathGlobalConfig = "config/globalconfig.json"
const PathTransferConfig = "config/transferconfig.json"
func main() {
conf := new(config.GlobalConfigurations)
err := conf.Parse(PathGlobalConfig)
if err != nil {
fmt.Println(err)
return
}
trans := new(config.TransferConfiguration)
err = trans.Parse(PathTransferConfig)
if err != nil {
fmt.Println(err)
return
}
m := make(map[string]*app.AddrConf)
for _, c := range *conf {
for _, a := range c.AddrStore {
m[a.Address] = &app.AddrConf{
UrlPort: `http://` + c.NodeIp + `:` + c.NodePort,
Password: a.Password,
}
}
}
a := app.App{
M: m,
Conf: conf,
Trans: trans,
}
a.Run()
return
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment