Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
M
multisend
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
李伟@五瓣科技
multisend
Commits
c66bf6c0
Commit
c66bf6c0
authored
Feb 17, 2022
by
李伟@五瓣科技
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
commit tx ok
parent
8b626404
Changes
6
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
726 additions
and
548 deletions
+726
-548
client_eth.go
client_eth.go
+169
-0
eth_network_info.go
eth_network_info.go
+256
-256
json.go
json.go
+216
-208
loadtest.go
loadtest.go
+55
-55
transactor.go
transactor.go
+9
-29
transactor_test.go
transactor_test.go
+21
-0
No files found.
client_eth.go
0 → 100644
View file @
c66bf6c0
package
multisend
import
(
"context"
"crypto/ecdsa"
"crypto/md5"
"fmt"
"math/big"
"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"
)
var
privatekey
string
=
"a1994419e9b06a7b27e8d094840ae26a6b7806633bb8be55a1a835f1620d8cec"
var
toAddress
common
.
Address
=
common
.
HexToAddress
(
"0x4592d8f8d7b001e72cb26a73e4fa1806a51ac79d"
)
// var data []byte = make([]byte, 0, md5.Size*(1000))
// func init() {
// privatekey = "a1994419e9b06a7b27e8d094840ae26a6b7806633bb8be55a1a835f1620d8cec"
// for i := 0; i < 8140; i++ {
// hash := md5.Sum([]byte(fmt.Sprintf("%d", i)))
// data = append(data, hash[:]...)
// }
// }
type
EthClientFactory
struct
{}
type
EthClient
struct
{
NodeRpcURL
string
}
var
_
ClientFactory
=
(
*
EthClientFactory
)(
nil
)
var
_
Client
=
(
*
EthClient
)(
nil
)
func
init
()
{
if
err
:=
RegisterClientFactory
(
"ethclient"
,
NewEthClientFactory
());
err
!=
nil
{
panic
(
err
)
}
}
func
NewEthClientFactory
()
*
EthClientFactory
{
return
&
EthClientFactory
{}
}
func
(
f
*
EthClientFactory
)
ValidateConfig
(
cfg
Config
)
error
{
return
nil
}
func
(
f
*
EthClientFactory
)
NewClient
(
cfg
Config
)
(
Client
,
error
)
{
return
&
EthClient
{
NodeRpcURL
:
"http://13.40.31.153:8545"
,
},
nil
}
func
(
c
*
EthClient
)
GenerateTx
()
(
*
types
.
Transaction
,
error
)
{
privateKeyAsECDSA
,
err
:=
crypto
.
HexToECDSA
(
privatekey
)
if
err
!=
nil
{
return
nil
,
err
}
publicKey
:=
privateKeyAsECDSA
.
Public
()
publicKeyECDSA
,
ok
:=
publicKey
.
(
*
ecdsa
.
PublicKey
)
if
!
ok
{
return
nil
,
fmt
.
Errorf
(
"publicKey.(*ecdsa.PublicKey) not ok"
)
}
fromAddress
:=
crypto
.
PubkeyToAddress
(
*
publicKeyECDSA
)
client
,
err
:=
ethclient
.
Dial
(
c
.
NodeRpcURL
)
if
err
!=
nil
{
return
nil
,
err
}
nonce
,
err
:=
client
.
PendingNonceAt
(
context
.
Background
(),
fromAddress
)
if
err
!=
nil
{
return
nil
,
err
}
gasPrice
,
err
:=
client
.
SuggestGasPrice
(
context
.
Background
())
if
err
!=
nil
{
return
nil
,
err
}
chainID
,
err
:=
client
.
NetworkID
(
context
.
Background
())
if
err
!=
nil
{
return
nil
,
err
}
txs
,
md5data
,
err
:=
getBatchTx
(
8000
,
c
.
NodeRpcURL
,
false
)
if
err
!=
nil
{
return
nil
,
err
}
_
=
txs
gasLimit
,
err
:=
client
.
EstimateGas
(
context
.
Background
(),
ethereum
.
CallMsg
{
To
:
&
toAddress
,
Data
:
md5data
,
})
tx
:=
types
.
NewTransaction
(
nonce
,
toAddress
,
big
.
NewInt
(
10000000000000
),
gasLimit
,
gasPrice
,
md5data
)
signedTx
,
err
:=
types
.
SignTx
(
tx
,
types
.
NewEIP155Signer
(
chainID
),
privateKeyAsECDSA
)
if
err
!=
nil
{
return
nil
,
err
}
return
signedTx
,
nil
}
func
getBatchTx
(
txNum
int
,
nodeUrl
string
,
signed
bool
)
([]
*
types
.
Transaction
,
[]
byte
,
error
)
{
res
:=
make
([]
*
types
.
Transaction
,
0
,
txNum
)
md5Data
:=
make
([]
byte
,
0
,
md5
.
Size
*
(
txNum
))
//publicKey := privateKey.Public()
// publicKeyECDSA, ok := publicKey.(*ecdsa.PublicKey)
// if !ok {
// log.Fatal("cannot assert type: publicKey is not of type *ecdsa.PublicKey")
// }
// fromAddress := crypto.PubkeyToAddress(*publicKeyECDSA)
// cli, err := ethclient.Dial(nodeUrl)
// if err != nil {
// log.Fatal(err)
// }
// nonce, err := cli.PendingNonceAt(context.Background(), fromAddress)
// if err != nil {
// log.Fatal(err)
// }
// gasLimit, err := cli.EstimateGas(context.Background(), ethereum.CallMsg{
// To: &toAddress,
// Data: data,
// })
// gasPrice, err := cli.SuggestGasPrice(context.Background())
// if err != nil {
// log.Fatal(err)
// }
// chainID, _ := cli.NetworkID(context.Background())
// fmt.Printf("gasLimit: %v gasPrice: %v chainID: %v \n", 4178026, 1000000000, 256)
privateKeyAsECDSA
,
err
:=
crypto
.
HexToECDSA
(
privatekey
)
if
err
!=
nil
{
return
nil
,
nil
,
err
}
for
i
:=
0
;
i
<
txNum
;
i
++
{
tx
:=
types
.
NewTransaction
(
0
+
uint64
(
i
),
toAddress
,
big
.
NewInt
(
10000000000000
),
4178026
,
big
.
NewInt
(
1000000000
),
nil
)
if
signed
{
signedTx
,
err
:=
types
.
SignTx
(
tx
,
types
.
NewEIP155Signer
(
big
.
NewInt
(
256
)),
privateKeyAsECDSA
)
//signedTx, err := types.SignTx(tx, types.NewEIP155Signer(chainID), privateKey)
if
err
!=
nil
{
return
nil
,
nil
,
err
}
tx
=
signedTx
}
txAsBytes
,
err
:=
tx
.
MarshalBinary
()
if
err
!=
nil
{
return
nil
,
nil
,
err
}
hash
:=
md5
.
Sum
(
txAsBytes
)
md5Data
=
append
(
md5Data
,
hash
[
:
]
...
)
res
=
append
(
res
,
tx
)
}
return
res
,
md5Data
,
nil
}
eth_network_info.go
View file @
c66bf6c0
This diff is collapsed.
Click to expand it.
json.go
View file @
c66bf6c0
This diff is collapsed.
Click to expand it.
loadtest.go
View file @
c66bf6c0
package
multisend
package
multisend
import
(
//
import (
"time"
//
"time"
"code.wuban.net.cn/multisend/internal/logging"
//
"code.wuban.net.cn/multisend/internal/logging"
)
//
)
func
ExecuteStandalone
(
cfg
Config
)
error
{
//
func ExecuteStandalone(cfg Config) error {
logger
:=
logging
.
NewLogrusLogger
(
"loadtest"
)
//
logger := logging.NewLogrusLogger("loadtest")
if
cfg
.
ExpectPeers
>
0
{
//
if cfg.ExpectPeers > 0 {
peers
,
err
:=
waitForEthNetworkPeers
(
//
peers, err := waitForEthNetworkPeers(
cfg
.
Endpoints
,
//
cfg.Endpoints,
cfg
.
EndpointSelectMethod
,
//
cfg.EndpointSelectMethod,
cfg
.
ExpectPeers
,
//
cfg.ExpectPeers,
cfg
.
MinConnectivity
,
//
cfg.MinConnectivity,
cfg
.
MaxEndpoints
,
//
cfg.MaxEndpoints,
time
.
Duration
(
cfg
.
PeerConnectTimeout
)
*
time
.
Second
,
//
time.Duration(cfg.PeerConnectTimeout)*time.Second,
logger
,
//
logger,
)
//
)
if
err
!=
nil
{
//
if err != nil {
logger
.
Error
(
"Failed while waiting for peers to connect"
,
"err"
,
err
)
//
logger.Error("Failed while waiting for peers to connect", "err", err)
return
err
//
return err
}
//
}
cfg
.
Endpoints
=
peers
//
cfg.Endpoints = peers
}
//
}
logger
.
Info
(
"Connecting to remote endpoints"
)
//
logger.Info("Connecting to remote endpoints")
tg
:=
NewTransactorGroup
()
//
tg := NewTransactorGroup()
if
err
:=
tg
.
AddAll
(
&
cfg
);
err
!=
nil
{
//
if err := tg.AddAll(&cfg); err != nil {
return
err
//
return err
}
//
}
logger
.
Info
(
"Initiating load test"
)
//
logger.Info("Initiating load test")
tg
.
Start
()
//
tg.Start()
var
cancelTrap
chan
struct
{}
//
var cancelTrap chan struct{}
if
!
cfg
.
NoTrapInterrupts
{
//
if !cfg.NoTrapInterrupts {
// we want to know if the user hits Ctrl+Break
//
// we want to know if the user hits Ctrl+Break
cancelTrap
=
trapInterrupts
(
func
()
{
tg
.
Cancel
()
},
logger
)
//
cancelTrap = trapInterrupts(func() { tg.Cancel() }, logger)
defer
close
(
cancelTrap
)
//
defer close(cancelTrap)
}
else
{
//
} else {
logger
.
Debug
(
"Skipping trapping of interrupts (e.g. Ctrl+Break)"
)
//
logger.Debug("Skipping trapping of interrupts (e.g. Ctrl+Break)")
}
//
}
if
err
:=
tg
.
Wait
();
err
!=
nil
{
//
if err := tg.Wait(); err != nil {
logger
.
Error
(
"Failed to execute load test"
,
"err"
,
err
)
//
logger.Error("Failed to execute load test", "err", err)
return
err
//
return err
}
//
}
logger
.
Info
(
"Load test complete!"
)
//
logger.Info("Load test complete!")
return
nil
//
return nil
}
//
}
transactor.go
View file @
c66bf6c0
...
@@ -13,16 +13,11 @@ import (
...
@@ -13,16 +13,11 @@ import (
"code.wuban.net.cn/multisend/internal/logging"
"code.wuban.net.cn/multisend/internal/logging"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/gorilla/websocket"
"github.com/gorilla/websocket"
//rpctypes "github.com/tendermint/tendermint/rpc/jsonrpc/types"
)
)
const
(
const
(
connSendTimeout
=
10
*
time
.
Second
connSendTimeout
=
10
*
time
.
Second
// see https://github.com/tendermint/tendermint/blob/master/rpc/lib/server/handlers.go
connPingPeriod
=
(
30
*
9
/
10
)
*
time
.
Second
connPingPeriod
=
(
30
*
9
/
10
)
*
time
.
Second
//jsonRPCID = rpctypes.JSONRPCStringID("tm-load-test")
defaultProgressCallbackInterval
=
5
*
time
.
Second
defaultProgressCallbackInterval
=
5
*
time
.
Second
)
)
...
@@ -85,12 +80,12 @@ func NewTransactor(remoteAddr string, config *Config) (*Transactor, error) {
...
@@ -85,12 +80,12 @@ func NewTransactor(remoteAddr string, config *Config) (*Transactor, error) {
logger
:=
logging
.
NewLogrusLogger
(
fmt
.
Sprintf
(
"transactor[%s]"
,
u
.
String
()))
logger
:=
logging
.
NewLogrusLogger
(
fmt
.
Sprintf
(
"transactor[%s]"
,
u
.
String
()))
logger
.
Info
(
"Connected to remote Tendermint WebSockets RPC"
)
logger
.
Info
(
"Connected to remote Tendermint WebSockets RPC"
)
return
&
Transactor
{
return
&
Transactor
{
remoteAddr
:
u
.
String
(),
remoteAddr
:
u
.
String
(),
config
:
config
,
config
:
config
,
client
:
client
,
client
:
client
,
logger
:
logger
,
logger
:
logger
,
conn
:
conn
,
conn
:
conn
,
broadcastTxMethod
:
"broadcast_tx_"
+
config
.
BroadcastTxMethod
,
//
broadcastTxMethod: "broadcast_tx_" + config.BroadcastTxMethod,
progressCallbackInterval
:
defaultProgressCallbackInterval
,
progressCallbackInterval
:
defaultProgressCallbackInterval
,
},
nil
},
nil
}
}
...
@@ -178,7 +173,6 @@ func (t *Transactor) sendLoop() {
...
@@ -178,7 +173,6 @@ func (t *Transactor) sendLoop() {
}
}
return
err
return
err
})
})
pingTicker
:=
time
.
NewTicker
(
connPingPeriod
)
pingTicker
:=
time
.
NewTicker
(
connPingPeriod
)
timeLimitTicker
:=
time
.
NewTicker
(
time
.
Duration
(
t
.
config
.
Time
)
*
time
.
Second
)
timeLimitTicker
:=
time
.
NewTicker
(
time
.
Duration
(
t
.
config
.
Time
)
*
time
.
Second
)
sendTicker
:=
time
.
NewTicker
(
time
.
Duration
(
t
.
config
.
SendPeriod
)
*
time
.
Second
)
sendTicker
:=
time
.
NewTicker
(
time
.
Duration
(
t
.
config
.
SendPeriod
)
*
time
.
Second
)
...
@@ -223,12 +217,6 @@ func (t *Transactor) sendLoop() {
...
@@ -223,12 +217,6 @@ func (t *Transactor) sendLoop() {
}
}
func
(
t
*
Transactor
)
writeTx
(
msg
interface
{})
error
{
func
(
t
*
Transactor
)
writeTx
(
msg
interface
{})
error
{
// txBase64 := base64.StdEncoding.EncodeToString(tx)
// paramsJSON, err := json.Marshal(map[string]interface{}{"tx": txBase64})
// if err != nil {
// return err
// }
// _ = t.conn.SetWriteDeadline(time.Now().Add(connSendTimeout))
err
:=
t
.
conn
.
WriteJSON
(
msg
)
err
:=
t
.
conn
.
WriteJSON
(
msg
)
return
err
return
err
}
}
...
@@ -248,13 +236,6 @@ func (t *Transactor) setStop(err error) {
...
@@ -248,13 +236,6 @@ func (t *Transactor) setStop(err error) {
t
.
stopMtx
.
Unlock
()
t
.
stopMtx
.
Unlock
()
}
}
// type requestOp struct {
// ids []json.RawMessage
// err error
// resp chan *jsonrpcMessage // receives up to len(ids) responses
// sub *ClientSubscription // only set for EthSubscribe requests
// }
func
(
t
*
Transactor
)
sendTransactions
()
error
{
func
(
t
*
Transactor
)
sendTransactions
()
error
{
// send as many transactions as we can, up to the send rate
// send as many transactions as we can, up to the send rate
totalSent
:=
t
.
GetTxCount
()
totalSent
:=
t
.
GetTxCount
()
...
@@ -285,11 +266,10 @@ func (t *Transactor) sendTransactions() error {
...
@@ -285,11 +266,10 @@ func (t *Transactor) sendTransactions() error {
args
:=
hexutil
.
Encode
(
data
)
args
:=
hexutil
.
Encode
(
data
)
method
:=
"eth_sendRawTransaction"
method
:=
"eth_sendRawTransaction"
msg
,
err
:=
t
.
newMessage
(
method
,
args
...
)
msg
,
err
:=
t
.
newMessage
(
method
,
args
)
if
err
!=
nil
{
if
err
!=
nil
{
return
err
return
err
}
}
//op := &requestOp{ids: []json.RawMessage{msg.ID}, resp: make(chan *jsonrpcMessage, 1)}
//op := &requestOp{ids: []json.RawMessage{msg.ID}, resp: make(chan *jsonrpcMessage, 1)}
//return ec.c.CallContext(ctx, nil, "eth_sendRawTransaction", hexutil.Encode(data))
//return ec.c.CallContext(ctx, nil, "eth_sendRawTransaction", hexutil.Encode(data))
if
err
:=
t
.
writeTx
(
msg
);
err
!=
nil
{
if
err
:=
t
.
writeTx
(
msg
);
err
!=
nil
{
...
...
transactor_test.go
View file @
c66bf6c0
...
@@ -2,8 +2,29 @@ package multisend
...
@@ -2,8 +2,29 @@ package multisend
import
(
import
(
"testing"
"testing"
"time"
)
)
func
TestTransactor
(
t
*
testing
.
T
)
{
func
TestTransactor
(
t
*
testing
.
T
)
{
cfg
:=
Config
{
Rate
:
10
,
Count
:
10
,
Connections
:
1
,
Time
:
60
,
SendPeriod
:
10
,
ClientFactory
:
"ethclient"
,
}
transactor
,
err
:=
NewTransactor
(
"ws://13.40.31.153:8546"
,
&
cfg
)
if
err
!=
nil
{
t
.
Error
(
err
)
}
//transactor.sendTransactions()
//transactor.sendLoop()
transactor
.
Start
()
time
.
Sleep
(
time
.
Second
*
60
)
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment